web-dev-qa-db-fra.com

Aspect ne fonctionne pas avec l'application de démarrage Printemps avec un fichier jar externe

J'essaie de créer un aspect de minuterie pour mesurer le temps d'exécution des méthodes.

J'ai créé une annotation nommée @Timer:

@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD, ElementType.TYPE})
public @interface Timer {
    String value();
}

Et puis j'ai créé l'aspect comme suit:

@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;
    }

J'ai une classe de configuration comme suit:

@Configuration
@EnableAspectJAutoProxy
public class MetricsConfiguration {

    @Bean
    public MetricAspect notifyAspect() {
        return new MetricAspect();
    }
}

Jusqu'à présent, tout est défini dans un fichier jar emballé que j'utilise comme dépendance dans mon application Spring Boot

Dans mon application de démarrage printanière, j'importe la variable MetricsConfiguration, j'ai débogué le code et constaté que le bean MetricAspect est créé.

Je l'utilise dans le code comme suit:

@Service
public class MyService {
    ...

    @Timer("mymetric")
    public void foo() {
       // Some code here...
    }

    ...
}

Mais mon code n'atteint pas la méthode measure. Pas sûr de ce que je manque.

Pour compléter la photo, j'ai ajouté ces dépendances dans mon fichier 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>

C'est la classe @Configuration qui importe MetricsConfiguration:

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

}

Il est chargé avec le chargement de configuration automagique de Spring.

10
Avi

@Component ou @Configurable peut-il résoudre votre problème?

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

Activer Spring AOP ou AspectJ

MODIFIER:

J'ai créé un projet pour simuler votre problème, ne semble pas être un problème après tout. Est-ce affecté par un autre problème?

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

10
ka yu Lai

J'ai eu un problème similaire où l'aspect a été construit dans une bibliothèque de jar, et l'application Spring-Boot était ailleurs. Il s'avère que les packages de l'application Spring-Boot et de la bibliothèque JAR étaient différents. En raison de quoi Spring n’examinait pas le paquet de la bibliothèque pour s’insérer automatiquement dans le contexte de l’application. 

Donc, il fallait inclure @ComponentScan({"base.package.application.*", "base.package.library.*"}) dans Application.Java

2
FMirza

Je n'ai pas pu reproduire votre problème avec aspectJ 1.8.8 et spring 4.2.5 . Ici est mon approche multi-module maven avec un aspect dans un bocal séparé.

J'ai légèrement modifié votre code mais je n'ai pas changé les annotations. La seule chose qui peut différer est que j'ai ajouté la dépendance org.springframework:spring-aop et défini mon point d'entrée comme suit:

@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();
    }
}
2
vsminkov
  1. Si le fichier jar externe est démarreur de démarrage Spring, vous pouvez configurer le bean Aspect dans la configuration automatique: 

(1)

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

(2)

package a.b.c

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

(3) config dans spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
a.b.c.MyAutoConfiguration
  1. Si le fichier JAR externe n’est pas un démarreur Spring Boot, il suffit de charger Aspect sous forme de haricot.
1
吴晓铭