[英]Aspect does not work with Spring boot application with external jar
我正在嘗試創建一個計時器方面來測量方法運行時間。
我創建了一個名為@Timer
的注釋:
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD, ElementType.TYPE})
public @interface Timer {
String value();
}
然后我按如下方式創建了方面:
@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;
}
我有一個配置類如下:
@Configuration
@EnableAspectJAutoProxy
public class MetricsConfiguration {
@Bean
public MetricAspect notifyAspect() {
return new MetricAspect();
}
}
到這里為止的所有內容都定義在一個打包的 jar 中,我將其用作 Spring Boot 應用程序中的依賴項
在我的 Spring Boot 應用程序中,我導入了MetricsConfiguration
並調試了代碼並看到創建了MetricAspect
bean。
我在代碼中使用它如下:
@Service
public class MyService {
...
@Timer("mymetric")
public void foo() {
// Some code here...
}
...
}
但是我的代碼沒有達到measure
方法。 不知道我錯過了什么。
為了完成圖片,我在我的 pom 文件中添加了這些依賴項:
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.7.4</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.7.4</version>
</dependency>
</dependencies>
這是導入MetricsConfiguration
的@Configuration
類:
@Configuration
@EnableAspectJAutoProxy
@Import(MetricsConfiguration.class)
@PropertySource("classpath:application.properties")
public class ApplicationConfiguration {
}
它加載了 Spring 的自動配置加載。
@Component
或@Configurable
解決您的問題嗎?
@Aspect
@Component
public class yourAspect {
...
}
編輯:
我創建了一個項目來模擬您的問題,畢竟似乎沒有問題。 是否受到其他問題的影響?
我無法使用aspectJ 1.8.8和spring 4.2.5重現您的問題。 這是我的 maven 多模塊方法,在單獨的 jar 中具有方面。
我稍微修改了您的代碼,但沒有更改任何注釋。 唯一可能不同的是我添加了org.springframework:spring-aop
依賴項並定義了我的入口點如下:
@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();
}
}
我有一個類似的問題,其中方面是在 jar 庫中構建的,而 spring-boot 應用程序在其他地方。 事實證明,spring-boot 應用程序和 jar 庫的包是不同的。 因此,Spring 沒有查看庫的包以自動裝配到應用程序上下文中。
因此,必須在@ComponentScan({"base.package.application.*", "base.package.library.*"})
包含@ComponentScan({"base.package.application.*", "base.package.library.*"})
(1)
@Aspect
public class MyAspect {
//....
}
(2)
package a.b.c
@Configuration
public class MyAutoConfiguration {
@Bean
MyAspect myAspect() {
return new MyAspect();
}
}
(3)spring.factories中的配置
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
a.b.c.MyAutoConfiguration
添加此組件掃描以解決問題。
@ComponentScan("package.of.aspect")
@Configuration
@EnableAspectJAutoProxy
@Import(MetricsConfiguration.class)
@PropertySource("classpath:application.properties")
public class ApplicationConfiguration {
}
即使有詳細的日志記錄,當切入點本身有問題時調試 spring-boot Aspectj 方面也並不容易: 如何調試 Spring AOP
不幸的是,帶有注解的spring boot + spring-aop 調試aspect 的方法並不多,以及為什么有些類,尤其是非spring 組件jar 類沒有被掃描,例如jar 類的方法在抽象類或靜態final 方法中需要正確的切入點來覆蓋所有類/實現,即使它們是組件掃描的。
調試 Asepct(或使用核心 AOP 並避免 spring-aop)的最佳方法是使用 org/aspectj/aop.xml 或 META-INF/aop.xml 啟用帶有配置控制的 aop.xml,使用 LTW aspectj weaver - Daj.weaving.verbose=true -javaagent:~/.m2/repository/org/aspectj/aspectjweaver/1.9.5/aspectjweaver-1.9.5.jar
使用 Debug/Verbose 日志調試所有方面/類以查看某些類未掃描的原因:...
這幾乎總是有助於找出切入點或類未被選中的問題。
或者,只使用 LTW aop,參見https://github.com/dsyer/spring-boot-aspectj
根據mojohaus 的解釋,您必須添加如下構建設置以將您的方面編織到實現方面接口的所有類中。
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.11</version>
<configuration>
<complianceLevel>1.8</complianceLevel>
<includes>
<include>**/*.java</include>
<include>**/*.aj</include>
</includes>
<aspectDirectory>src/main/aspect</aspectDirectory>
<testAspectDirectory>src/test/aspect</testAspectDirectory>
<XaddSerialVersionUID>true</XaddSerialVersionUID>
<showWeaveInfo>true</showWeaveInfo>
<aspectLibraries>
<aspectLibrary>
<groupId>your aspect groupId</groupId>
<artifactId>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>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.runtime.version}</version>
</dependency>
<dependency>
<groupId>your aspect groupId</groupId>
<artifactId>youar aspect artifactId</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.