web-dev-qa-db-ja.com

アスペクトが外部jarを含むSpringブートアプリケーションで動作しない

メソッドの実行時間を測定するためのタイマーアスペクトを作成しようとしています。

@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で定義されています

私のスプリングブートアプリケーションで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の自動設定ロードでロードされます。

16
Avi

できる @Componentまたは@Configurable問題を解決しますか?

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

Spring AOPまたはAspectJを有効にする

編集:

あなたの問題をシミュレートするプロジェクトを作成しましたが、結局問題ないようです。他の問題の影響を受けますか?

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

12
ka yu Lai

aspectJ 1.8.8およびspring 4.2.5を使用して問題を再現できませんでした。 ここ は、別のjarにアスペクトを持つ私のmavenマルチモジュールアプローチです。

コードを少し変更しましたが、アノテーションは変更しませんでした。異なる可能性があるのは、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();
    }
}
4
vsminkov
  1. 外部jarがSpringブートスターターである場合、AutoConfigurationでアスペクトBeanを構成できます。

(1)

@Aspect
public class MyAspect {
  //....
}

(2)

package a.b.c

@Configuration
public class MyAutoConfiguration {
    @Bean
    MyAspect myAspect() {
        return new MyAspect();
    }   
}

(3)spring.factoriesのconfig

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
a.b.c.MyAutoConfiguration
  1. 外部jarがSpringブートスターターではない場合、AspectをBeanとしてロードするだけで、@ ComponentScanを使用できます
2
吴晓铭

アスペクトがjarライブラリに構築されている場合も同様の問題があり、Spring-Bootアプリケーションが別の場所にありました。 Spring-Bootアプリケーションとjarライブラリのパッケージが異なることがわかりました。 Springがライブラリのパッケージを調べて、アプリケーションコンテキストに自動配線していなかったためです。

したがって、Application.Javaに@ComponentScan({"base.package.application.*", "base.package.library.*"})を含める必要がありました。

2
FMirza

このコンポーネントを追加して問題を解決してください。

@ComponentScan("package.of.aspect")
@Configuration
@EnableAspectJAutoProxy
@Import(MetricsConfiguration.class)
@PropertySource("classpath:application.properties")
public class ApplicationConfiguration {

}
0
Asaf Maoz