为什么Spring会初始化我的Aspect两次?

问题描述 投票:2回答:2

我有一个简单的方面是围绕一个方法做一些逻辑。我正在使用Spring Boot和AspjectJ。出于某种原因,方面的构造函数被调用两次。

我的方面看起来像这样:

@Aspect
@Component
public class HandlerLoggingAspect {
  private static final Logger log = LoggerFactory.getLogger(HandlerLoggingAspect.class);

  public HandlerLoggingAspect() {
    log.info("Initialising HandlerLoggingAspect");
  }

  @Around("execution (* io.netty.handler.codec.ByteToMessageDecoder+.decode(*,*,*)) && args(ctx,byteBuf,outList)")
  public void interceptByteDecoding(ProceedingJoinPoint joinPoint, ChannelHandlerContext ctx, ByteBuf byteBuf, List<Object> outList) throws Throwable {
    setupMdcAroundJoinPoint(joinPoint, ctx);
  }

 //... rest of the code ...
}

该方面在我期望的方法中运行良好,但出于某种原因Spring Boot正在初始化我的方面两次。 Intialising HandlerLoggingAspect消息在开始时出现两次。

2016-09-25 18:36:26.041 [main] DEBUG  Running with Spring Boot v1.4.0.RELEASE, Spring v4.3.2.RELEASE
2016-09-25 18:36:26.041 [main] INFO   No active profile set, falling back to default profiles: default
2016-09-25 18:36:29.891 [main] INFO   Initialising HandlerLoggingAspect
2016-09-25 18:36:29.892 [main] INFO   Initialising HandlerLoggingAspect

如果我从Aspect中删除@Component,它根本就没有初始化。

我的主要课程如下:

@ComponentScan
@Configuration
@EnableAutoConfiguration
@EnableAspectJAutoProxy
@SpringBootApplication
public class Launcher implements CommandLineRunner {
  private static final Logger log = LoggerFactory.getLogger(Launcher.class);

  public static void main(String[] args) {
    SpringApplication.run(Launcher.class, args);
  }

  @Override
  public void run(String... strings) throws Exception {
     //... logic performed by the class ...
  }
}

如果它有任何区别,这是我在pom.xml中为AspectJ编译时编织的插件配置。

<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
        <maven-compiler-plugin.version>3.5.1</maven-compiler-plugin.version>
        <aspectj-maven-plugin.version>1.8</aspectj-maven-plugin.version>
        <org.aspectj.version>1.8.9</org.aspectj.version>

        <org.springframework.boot.version>1.4.0.RELEASE</org.springframework.boot.version>
    </properties>

...
       <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>${maven-compiler-plugin.version}</version>
            <configuration>
                <source>${java.version}</source>
                <target>${java.version}</target>
                <proc>none</proc>
            </configuration>
        </plugin>

        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>aspectj-maven-plugin</artifactId>
            <version>${aspectj-maven-plugin.version}</version>
            <configuration>
                <complianceLevel>${java.version}</complianceLevel>
                <source>${java.version}</source>
                <target>${java.version}</target>
                <showWeaveInfo/>
                <forceAjcCompile>true</forceAjcCompile>
                <sources/>
                <weaveDirectories>
                    <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
                </weaveDirectories>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>compile</goal>       <!-- use this goal to weave all your main classes -->
                        <goal>test-compile</goal>  <!-- use this goal to weave all your test classes -->
                    </goals>
                </execution>
            </executions>
            <dependencies>
                <dependency>
                    <groupId>org.aspectj</groupId>
                    <artifactId>aspectjtools</artifactId>
                    <version>${org.aspectj.version}</version>
                </dependency>
            </dependencies>
        </plugin>

当我分析其余的日志时,似乎只有一个实例实际上拦截了切入点。所以至少这是好事。

这种双重初始化的原因是什么?

**更多信息**

似乎在Spring文档中,提到了有关Aspects初始化两次的内容。

http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/aop.html#aop-proxying

但它说下面的内容(我使用的是Spring 4.3.2):

从Spring 4.0开始,代理对象的构造函数将不再被调用两次,因为CGLIB代理实例将通过Objenesis创建。只有当您的JVM不允许构造函数绕过时,您才会看到Spring的AOP支持中的双重调用和相应的调试日志条目。

还写了以下内容,因为我使用的是@EnableAspectJAutoProxy注释,所以也应该适用,所以我知道我使用的是CGLIB代理:

需要明确的是:在proxy-target-class="true"上使用<tx:annotation-driven/><aop:aspectj-autoproxy/><aop:config/>元素将强制使用CGLIB代理所有这三个。

我使用的是Java 1.8。我正在使用的组件组合之间是否存在任何已知的不兼容性,这会阻止上述构造函数绕过?

java spring-boot java-8 aspectj spring-aop
2个回答
0
投票

我在Spring应用程序中找到了使用AspectJ的Spring文档的详细说明。正如它所说的那样:“这确保Spring通过向AspectJ询问它来获取方面实例,而不是尝试自己创建实例。”,您可以从中找到示例:

<bean id="profiler" class="com.xyz.profiler.Profiler" factory-method="aspectOf">
    <property name="profilingStrategy" ref="jamonProfilingStrategy"/>
</bean>

希望它能帮到你。


0
投票

尝试使用其他编译器,如果您使用的是Ajc,请从IDE设置中将其更改为其他内容;它对我有用。

© www.soinside.com 2019 - 2024. All rights reserved.