Search code examples
springspring-aop

@within did not execute in spring-aop


As per my understanding, @within would execute if an annotation is at the class level so as per that understanding below snippet should run the @within block.

example6

but my output did not print @within advice values. why?


Solution

  • Your main class only calls testService.test, but that method is not annotated by @Log. So why are you expecting it to be intercepted by the aspect? Also, there is only class AnnotatedWithinTestImpl in the within package, but you are not executing any code from it.

    Adding

    AnnotatedWithinTestImpl annotatedWithinTest = (AnnotatedWithinTestImpl) context.getBean("annotatedWithinTest");
    annotatedWithinTest.test();
    

    to your main method should trigger the testAllBeansWithAnnotation advice and print:

    WITHIN ANNOTATION LOG: CALL METHOD (...) within.AnnotatedWithinTestImpl#test with args []
    

    For me, locally that works after adding the missing pieces of your code snippets.


    Update: Thanks for the reproducer on GitHub. Now I can really reproduce and see what you did wrong. You use an @Around advice without calling jp.proceed(), i.e. the target method execution is blocked in the first advice. The second one therefore never fires. So

    • either make sure that both advices proceed and return the proceed result,
    • or, because you neither want to modify method parameters nor the method result, just switch from @Around to a simpler @Before or @After advice, then it works like a charm and there is no need to proceed or return anything.

    This is all described in the Spring AOP manual.

    The second option looks like this:

        @Order(2)
        @Before("allBeans()")
        public void testAllBeans(JoinPoint jp) {
            LOGGER.setLevel(Level.FINEST);
            ConsoleHandler consoleHandler = new ConsoleHandler();
            consoleHandler.setLevel(Level.FINE); // set console handler logging level to FINE
            LOGGER.addHandler(consoleHandler);
            String type = jp.getSignature().getDeclaringTypeName();
            String methodName = jp.getSignature().getName();
            Object[] methodArgs = jp.getArgs();
            print("WITHIN LOG: CALL METHOD " + type + "#" + methodName + " with args " + Arrays.toString(methodArgs));
        }
    
        @Order(1)
        @Before("allBeansWithAnnotation()")
        public void testAllBeansWithAnnotation(JoinPoint jp) {
            LOGGER.setLevel(Level.FINEST);
            ConsoleHandler consoleHandler = new ConsoleHandler();
            consoleHandler.setLevel(Level.FINE); // set console handler logging level to FINE
            LOGGER.addHandler(consoleHandler);
            String type = jp.getSignature().getDeclaringTypeName();
            String methodName = jp.getSignature().getName();
            Object[] methodArgs = jp.getArgs();
            print("WITHIN ANNOTATION LOG: CALL METHOD " + type + "#" + methodName + " with args " + Arrays.toString(methodArgs));
        }
    

    The console log then is:

    WITHIN LOG: CALL METHOD com.springaop.example6.within.WithinTest#test with args []
    WITHIN ANNOTATION LOG: CALL METHOD com.springaop.example6.within.WithinTest#test with args []
    

    P.S.: Next time, please test your MCVE. You still had some old package names in your pointcuts, pointing to bogus packages.