javaspringinterceptorspring-aopmethod-interception

Using MethodInterceptor in Spring


I have the following configuration to intercept a method and apply advice after returning from method, But, the following configuration does not work. Could you suggest on what I am missing?

@Service("txnEventSubscriber")
EventSubscriberImpl
...

@Resource(name="txnEventSubscriber")
    private EventSubscriberImpl subscriber;


    @Bean
    public Advice myAdvice() {
        return new AfterReturningAdvice() {
            @Override
            public void afterReturning(Object returnValue, Method method, Object[] args, Object target)
            {
                System.out.println("inside advice");
            }
        };
    }

    @Bean
    public ProxyFactoryBean myProxyFactoryBean() {
        return new ProxyFactoryBean() {
            private static final long serialVersionUID = 6296720408391985671L;

            @PostConstruct
            public void afterPropertiesSet() throws ClassNotFoundException {
                setTarget(subscriber);
                setInterceptorNames(new String[] {"myAdvice"});
            }
        };
    }

I have the EventSubscriber which when invoked and when method is returned, I need to intercept the method call and do something... in this case, print "inside advice".

I am not seeing any exceptions, just method advice is not getting called.


Solution

  • First of all, I see you have the class name as EventSubscriberImpl and you are injecting the same type of class. Meaning, you are not programming to interfaces. In this case, you would want to setProxyTargetClass(true); for your ProxyFactoryBean bean and put CGLIB in your project's classpath.

    Secondly, you would need something like this

    @Resource(name="myProxyFactoryBean")
    private EventSubscriberImpl subscriber;
    

    whenever you want to use the proxied version of your EventSubscriberImpl. Meaning, you need to explicitly get that proxied bean by its proxied bean name.

    Thirdly, I'd use something like this, to avoid getting the bean by its proxied name:

    @Resource(name="txnEventSubscriber")
    private EventSubscriberImpl subscriber;
    
    @Bean
    public Advice myAdvice() {
        return new AfterReturningAdvice() {
            public void afterReturning(Object returnValue, Method method, Object[] args, Object target)
            {
                System.out.println("inside advice");
            }
        };
    }
    
    @Bean
    public Advisor myAdvisor() {
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression("execution(public * com.foo.bar.EventSubscriberImpl.*(..))");
        return new DefaultPointcutAdvisor(pointcut, myAdvice());
    }