首页 文章

Aspect不适用于带有外部jar的Spring启动应用程序

提问于
浏览
12

我正在尝试为测量方法运行时创建一个计时器方面 .

我创建了一个名为 @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();
    }
}

Everything up until here is defined in a packaged jar which I use as a dependency in my spring boot application

在我的 Spring 季启动应用程序中,我导入了 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的自动配置加载 .

4 回答

  • 1

    可以 @Component@Configurable 解决您的问题?

    @Aspect
    @Component
    public class yourAspect {
     ...
    }
    

    Enable Spring AOP or AspectJ

    编辑:

    我创建了一个模拟你的问题的项目,毕竟没问题 . 是否受其他问题的影响?

    https://github.com/zerg000000/spring-aspectj-test

  • 2

    我无法使用aspectJ 1.8.8和spring 4.2.5重现您的问题 . Here是我的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();
        }
    }
    
  • 10

    我有一个类似的问题,其中方面是在一个jar库中构建的,而spring-boot应用程序则是在其他地方 . 事实证明,spring-boot应用程序和jar库的包是不同的 . 由于Spring没有查看库的包,无法自动装入应用程序上下文 .

    因此,必须在Application.java中包含 @ComponentScan({"base.package.application.*", "base.package.library.*"})

  • 2
    • 如果外部jar是Spring启动程序,则可以在AutoConfiguration中配置Aspect bean:

    (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
    
    • 如果外部jar不是Spring引导启动器,只需将Aspect加载为bean,就可以使用@ComponentScan

相关问题