Search code examples
javaspring-bootannotationsaspectj

@Aspect not called when using annotation


I create an annotation to make some operations as bellow:

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

and an Aspect:

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

and a config:

@Configuration
@EnableAspectJAutoProxy
public class VerifyConfig {
}

But when I call:

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

The Aspect not called at all. do I make any mistake in my creation?


Solution

  • From the spring docs : Spring AOP currently supports only method execution join points (advising the execution of methods on Spring beans) - So make sure, the method you are calling

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

    is declared inside one of the Spring Beans.

    Based on the code you've shared, I created a simple demo:

    Also make sure, the aspectjweaver.jar is in your dependencies

    pom.xml

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

    Main Application

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

    Configuration

    Here, make sure you provide the correct basePackages for Spring to scan for your components

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

    Annotation

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

    Aspect

    @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

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

    And the output from the console, when I call http://localhost:8080/sample endpoint:

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

    Second line is what you wanted to see printed.