我有一个简单的方面是围绕一个方法做一些逻辑。我正在使用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初始化两次的内容。
然而它说下面的内容(我使用的是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。我使用的组件组合之间是否存在任何已知的不兼容性,这会阻止上述构造函数绕过?
答案 0 :(得分:0)
我发现了有关将AspectJ与Spring应用程序一起使用的Spring文档的说明。就像它说的:“这确保Spring通过向AspectJ索要长宽比实例,而不是尝试自己创建实例来获取。”,您可以从中找到实例:
<bean id="profiler" class="com.xyz.profiler.Profiler" factory-method="aspectOf">
<property name="profilingStrategy" ref="jamonProfilingStrategy"/>
</bean>
希望对您有帮助。
答案 1 :(得分:0)
尝试使用其他编译器,如果使用的是Ajc,请从IDE设置将其更改为其他名称;它对我有用。