@Before @PostConstruct Spring AOP 拦截
@Before @PostConstruct Spring AOP ineterception
我正在尝试编写一个可以拦截 PostConstruct 方法的方面。我已经查看了 SO 和其他人的相关问题,并关注了它们,这就是我到目前为止所拥有的:
Spring配置
@Configuration
@EnableAspectJAutoProxy
@EnableLoadTimeWeaving
@...//other config annotations
public class WebConfiguration {
@Bean
public CommonAnnotationBeanPostProcessor commonAnnotationBeanPostProcessor() {
return new CommonAnnotationBeanPostProcessor();
}
... // etc
}
注解:
@Retention(RetentionPolicy.RUNTIME)
public @interface Secured {
Permission[] permissions() default {};
}
豆子
@Component
@Scope("request")
public class SomeWebBean {
@Secured(permissions = Permission.SOME_PERMISSION)
@PostConstruct
public void secure() {
... // some stuff
}
}
看点
@Component
@Aspect
public class SecuredAspect {
@Before("@annotation(secured)")
public void doAccessCheck(Secured secured) {
... // actually do the access check
}
}
如果我从页面调用 someWebBean.secure()
,则会调用方面。但是,它不会在创建 bean 时调用。
因此,作为对未来我的说明 - 这绝对不能使用 Spring AOP 以这种方式完成。
但是,同样的效果可以通过如下实现 BeanPostProcessor 来实现:
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;
}
}
您可以扩展 CommonAnnotationBeanPostProcessor 并覆盖 postProcessBeforeInitialization(Object bean, String beanName)
然后注册用BeanFactoryPostProcessor替换原来的CommonAnnotationBeanPostProcessor。
public class InitCommonAnnotationBeanPostProcessor extends CommonAnnotationBeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return super.postProcessBeforeInitialization(bean, beanName);
}
}
public class InitBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
RootBeanDefinition def = new RootBeanDefinition(InitCommonAnnotationBeanPostProcessor.class);
def.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AnnotationConfigUtils.COMMON_ANNOTATION_PROCESSOR_BEAN_NAME, def);
}
}
@Configuration
public class InitialisationMonitoringConfig {
public static final String BEAN_INIT_MONITOR = "BEAN_INIT_MONITOR";
@Bean
public static InitBeanFactoryPostProcessor initBeanFactoryPostProcessor() {
return new InitBeanFactoryPostProcessor();
}
}
这很丑陋,但我必须这样做才能分析开发环境中的启动时间。
也许只将 InitCommonAnnotationBeanPostProcessor 声明为 bean 就足够了,我没试过。
我正在尝试编写一个可以拦截 PostConstruct 方法的方面。我已经查看了 SO 和其他人的相关问题,并关注了它们,这就是我到目前为止所拥有的:
Spring配置
@Configuration
@EnableAspectJAutoProxy
@EnableLoadTimeWeaving
@...//other config annotations
public class WebConfiguration {
@Bean
public CommonAnnotationBeanPostProcessor commonAnnotationBeanPostProcessor() {
return new CommonAnnotationBeanPostProcessor();
}
... // etc
}
注解:
@Retention(RetentionPolicy.RUNTIME)
public @interface Secured {
Permission[] permissions() default {};
}
豆子
@Component
@Scope("request")
public class SomeWebBean {
@Secured(permissions = Permission.SOME_PERMISSION)
@PostConstruct
public void secure() {
... // some stuff
}
}
看点
@Component
@Aspect
public class SecuredAspect {
@Before("@annotation(secured)")
public void doAccessCheck(Secured secured) {
... // actually do the access check
}
}
如果我从页面调用 someWebBean.secure()
,则会调用方面。但是,它不会在创建 bean 时调用。
因此,作为对未来我的说明 - 这绝对不能使用 Spring AOP 以这种方式完成。
但是,同样的效果可以通过如下实现 BeanPostProcessor 来实现:
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;
}
}
您可以扩展 CommonAnnotationBeanPostProcessor 并覆盖 postProcessBeforeInitialization(Object bean, String beanName)
然后注册用BeanFactoryPostProcessor替换原来的CommonAnnotationBeanPostProcessor。
public class InitCommonAnnotationBeanPostProcessor extends CommonAnnotationBeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return super.postProcessBeforeInitialization(bean, beanName);
}
}
public class InitBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
RootBeanDefinition def = new RootBeanDefinition(InitCommonAnnotationBeanPostProcessor.class);
def.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AnnotationConfigUtils.COMMON_ANNOTATION_PROCESSOR_BEAN_NAME, def);
}
}
@Configuration
public class InitialisationMonitoringConfig {
public static final String BEAN_INIT_MONITOR = "BEAN_INIT_MONITOR";
@Bean
public static InitBeanFactoryPostProcessor initBeanFactoryPostProcessor() {
return new InitBeanFactoryPostProcessor();
}
}
这很丑陋,但我必须这样做才能分析开发环境中的启动时间。
也许只将 InitCommonAnnotationBeanPostProcessor 声明为 bean 就足够了,我没试过。