@Аспект не вызывается при использовании аннотации

#java #spring-boot #annotations #aspectj

#java #весенняя загрузка #аннотации #aspectj

Вопрос:

Я создаю аннотацию для выполнения некоторых операций, как показано ниже:

 @Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER})
public @interface Verify {
}
  

и аспект:

 @Aspect
@Component
public class VerifyAspect {
    @Before("execution(public * *(.., @Verify (*), ..))")
    public void actionBefore(JoinPoint joinPoint) {
       System.out.println(joinPoint); // <<-------------- can't see this message
    }
}
  

и конфигурация:

 @Configuration
@EnableAspectJAutoProxy
public class VerifyConfig {
}
  

Но когда я вызываю:

 public void method(@Verify MyObject obj){
   // do something
}
  

Аспект вообще не вызывается. допускаю ли я какую-либо ошибку в своем создании?

Ответ №1:

Из spring docs : Spring AOP в настоящее время поддерживает только точки соединения выполнения метода (рекомендующие выполнение методов в Spring beans) — Поэтому убедитесь, что вызываемый вами метод

 public void method(@Verify MyObject obj){
   // do something
}
  

объявлено внутри одного из компонентов Spring.

На основе кода, которым вы поделились, я создал простую демонстрацию:

Также убедитесь, что aspectjweaver.jar находится в ваших зависимостях

pom.xml

         <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.6</version>
        </dependency>
  

Основное приложение

 @SpringBootApplication
public class AspecjStyleAopApplication {

    public static void main(String[] args) {
        SpringApplication.run(AspecjStyleAopApplication.class, args);
    }

}
  

Конфигурация

Здесь убедитесь, что вы предоставили правильные базовые пакеты для Spring для сканирования ваших компонентов

 @Configuration
@EnableAspectJAutoProxy
@ComponentScan(basePackages = "com.example")
public class AspectJConfig {
}
  

Аннотация

 @Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER})
public @interface Verify {
}
  

Аспект

 @Aspect
@Component
public class VerifyAspect {

    @Before("execution(public * *(.., @Verify (*), ..))")
    public void actionBefore(JoinPoint joinPoint) {
        System.out.println("THIS SHOULD BE DISPLAYED");
        System.out.println(joinPoint); // <<-------------- can't see this message
    }
}
  

Обслуживание

 @Service
public class SampleService {

    public void method(@Verify Object obj){
        System.out.println("Passed object: "   obj);
    }
}
  

RestController

 @RestController
public class SampleRestController {

    private final SampleService sampleService;

    public SampleRestController(SampleService sampleService) {
        this.sampleService = sampleService;
    }

    @GetMapping("/sample")
    public String sampleRestMethod() {
        sampleService.method(5);
        return "It works";
    }
}
  

И вывод из консоли, когда я вызываю http://localhost:8080/sample конечную точку:

 THIS SHOULD BE DISPLAYED
execution(void com.example.aspecjstyleaop.SampleService.method(Object))
Passed object: 5
  

Вторая строка — это то, что вы хотели видеть напечатанным.

Комментарии:

1. Да, он вызывается из аннотированного класса @Service Я также пытался вызвать его из @RestController , но без шансов

2. Вы уверены? Я сделал несколько демонстрационных примеров, и для меня это работает просто отлично.

3. Да, я уверен, у меня есть такой метод, @Service public class MyServiceService { public void method(@Verify MyDto dto) { System.out.println("Method"); } } и я вызываю его из @RestController , но он не показывает мне никакого сообщения, что означает, что он вообще не вызывает аспект

4. Не могли бы вы поделиться полным примером, пожалуйста? возможно, я что-то забыл или какую-то конфигурацию

5. Спасибо за полный код, но он все еще не работает со мной, вы импортируете что-нибудь в pom.xml ?