#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 ?