Aspect does not work with Spring boot application with external jar
我正在尝试创建一个用于测量方法运行时间的计时器方面。
我创建了一个名为
1 2 3 4 5 |
然后,我创建了如下方面:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | @Aspect public class MetricAspect { @Autowired private MetricsFactory metricsFactory; @Pointcut("@annotation(my.package.Timer)") public void timerPointcut() {} @Around("timerPointcut()") public Object measure(ProceedingJoinPoint joinPoint) throws Throwable { /* Aspect logic here */ } private Timer getClassAnnotation(MethodSignature methodSignature) { Timer annotation; Class< ? > clazz = methodSignature.getDeclaringType(); annotation = clazz.getAnnotation(Timer.class); return annotation; } |
我有一个配置类,如下所示:
1 2 3 4 5 6 7 8 9 | @Configuration @EnableAspectJAutoProxy public class MetricsConfiguration { @Bean public MetricAspect notifyAspect() { return new MetricAspect(); } } |
直到这里的所有内容都在打包的jar中定义,我在Spring Boot应用程序中将其用作依赖项
在我的Spring Boot应用程序中,导入
我在代码中如下使用它:
1 2 3 4 5 6 7 8 9 10 11 | @Service public class MyService { ... @Timer("mymetric") public void foo() { // Some code here... } ... } |
但是我的代码没有达到
为了完成图片,我在pom文件中添加了以下依赖项:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <dependencies> <dependency> <groupId>org.aspectj</groupId> aspectjweaver</artifactId> <version>1.7.4</version> </dependency> <dependency> <groupId>org.aspectj</groupId> aspectjrt</artifactId> <version>1.7.4</version> </dependency> </dependencies> |
那就是导入
1 2 3 4 5 6 7 | @Configuration @EnableAspectJAutoProxy @Import(MetricsConfiguration.class) @PropertySource("classpath:application.properties") public class ApplicationConfiguration { } |
它由Spring的自动配置加载加载。
1 2 3 4 5 |
启用S??pring AOP或AspectJ
编辑:
我创建了一个项目来模拟您的问题,毕竟似乎没有问题。是否受其他问题影响?
https://github.com/zerg000000/spring-aspectj-test
我无法使用AspectJ 1.8.8和spring 4.2.5重现您的问题。这是我的Maven多模块方法,其方面在单独的jar中。
我稍微修改了您的代码,但未更改任何注释。唯一可能不同的是,我添加了
1 2 3 4 5 6 7 8 9 10 11 | @Import(MetricsConfiguration.class) @SpringBootApplication public class Application { // @Bean definitions here // public static void main(String[] args) throws InterruptedException { ApplicationContext ctx = SpringApplication.run(Application.class, args); ctx.getBean(MyService.class).doWork(); } } |
(1)
1 2 3 4 | @Aspect public class MyAspect { //.... } |
(2)
1 2 3 4 5 6 7 8 9 | package a.b.c @Configuration public class MyAutoConfiguration { @Bean MyAspect myAspect() { return new MyAspect(); } } |
(3)在spring.factories中配置
1 2 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\\ a.b.c.MyAutoConfiguration |
我有一个类似的问题,方面是在jar库中构建的,而spring-boot应用程序在其他地方。原来,spring-boot应用程序和jar库的软件包不同。由于这个原因,Spring并没有考虑将库的程序包自动装配到应用程序上下文中。
因此,必须在Application.java中包含
即使有详细的日志记录,在切入点本身有问题时也无法调试spring-boot Aspectj方面:如何调试Spring AOP
不幸的是,带有注释的spring boot + spring-aop并没有很多调试方面的方法,以及为什么不扫描某些类,尤其是非spring compoment jar类,例如其类在抽象类或静态final方法中的jar类。需要正确的切入点以覆盖所有类/实现,即使它们是组件扫描的。
调试Asepct的最佳方法(或使用核心AOP并避免spring-aop)是使用LTW Aspectj Weaver使用org / aspectj / aop.xml或META-INF / aop.xml进行配置控制来启用aop.xml。
-Daj.weaving.verbose = true -javaagent:?/ .m2 / repository / org / aspectj / aspectjweaver / 1.9.5 / aspectjweaver-1.9.5.jar
要使用调试/详细日志调试所有方面/类,以查看为什么未扫描某些类:
...
这几乎总是可以帮助解决切入点或类未被选择的问题。
或者,仅使用LTW aop,请参阅https://github.com/dsyer/spring-boot-aspectj
添加此componentScan以解决问题。
1 2 3 4 5 6 7 8 | @ComponentScan("package.of.aspect") @Configuration @EnableAspectJAutoProxy @Import(MetricsConfiguration.class) @PropertySource("classpath:application.properties") public class ApplicationConfiguration { } |
根据mojohaus的解释,您必须将如下所示的构建设置添加到Woven方面,并将其编织到实现方面接口的所有类中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | <build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> aspectj-maven-plugin</artifactId> <version>1.11</version> <configuration> <complianceLevel>1.8</complianceLevel> <includes> <include>**/*.java</include> <include>**/*.aj</include> </includes> src/main/aspect</aspectDirectory> <testAspectDirectory>src/test/aspect</testAspectDirectory> <XaddSerialVersionUID>true</XaddSerialVersionUID> <showWeaveInfo>true</showWeaveInfo> <groupId>your aspect groupId</groupId> your aspect artifactId</artifactId> </aspectLibrary> </aspectLibraries> </configuration> <executions> <execution> <id>compile_with_aspectj</id> <goals> <goal>compile</goal> </goals> </execution> <execution> <id>test-compile_with_aspectj</id> <goals> <goal>test-compile</goal> </goals> </execution> </executions> <dependencies> <dependency> <groupId>org.aspectj</groupId> aspectjtools</artifactId> <version>${aspectj.runtime.version}</version> </dependency> <dependency> <groupId>your aspect groupId</groupId> youar aspect artifactId</artifactId> <version>1.0.0-SNAPSHOT</version> </dependency> </dependencies> </plugin> </plugins> </build> |