Search code examples
springaopaspectjpostconstruct

@Before @PostConstruct Spring AOP ineterception


I'm trying to write an aspect that can intercept PostConstruct methods. I've looked at related questions on SO and others, and following them, this is what I have so far:

The Spring configuration

@Configuration
@EnableAspectJAutoProxy
@EnableLoadTimeWeaving
@...//other config annotations
public class WebConfiguration {

    @Bean
    public CommonAnnotationBeanPostProcessor commonAnnotationBeanPostProcessor() {
        return new CommonAnnotationBeanPostProcessor();
    }
    ... // etc

}

The annotation:

@Retention(RetentionPolicy.RUNTIME)
public @interface Secured {
    Permission[] permissions() default {};
}

The bean

@Component
@Scope("request")
public class SomeWebBean {

    @Secured(permissions = Permission.SOME_PERMISSION)
    @PostConstruct
    public void secure() {
        ... // some stuff
    }

}

The aspect

@Component
@Aspect
public class SecuredAspect {

    @Before("@annotation(secured)")
    public void doAccessCheck(Secured secured) {
        ... // actually do the access check
    }

}

If I call someWebBean.secure() from a page, then the aspect is invoked. However, it is not invoked on bean creation.


Solution

  • So as a note to future me - this absolutely cannot be done in this way using Spring AOP.

    However, the same effect can be achieved by implementing a BeanPostProcessor as below:

    public class SecureBeanPostProcessor implements BeanPostProcessor {
    
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            Secured secured = bean.getClass().getAnnotation(Secured.class);
            if (secured != null) {
                // do your security test here, throw an exception, return false, however you like
            }
            return bean;
        }
    
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            return bean;
        }
    }