spring动态注册bean AOP失效原理解析
前言
本文的素材来自读者的一个问题,他看过我之前写的一篇博文聊聊如何把第三方服务注册到我们项目的spring容器中。刚好他项目中也有类似这样的一个需求,他就采用我文中介绍的第三种方法
调用beanFactory.registerSingleton()
一开始项目运行得还可以,后面他在这个第三方服务中使用AOP,发现AOP始终没有生效。于是他就给我留言了。今天就来聊一下这个话题,为什么使用registerSingleton()注册的bean,无法使AOP生效
问题根源
registerSingleton()这个方法直接将bean存放到单例池里面了。
如果对bean的生命周期有了解的朋友,应该会知道,bean可能会经过一系列的后置处理器后,再存放到单例池里面。因此这个bean可能是会被增强的,其中当然包括经过AOP增强
而使用registerSingleton()相当于是直接走捷径,不经过后置处理器,一步到位直接存放到单例池中。如果第三方服务是直接通过new出来的,就是一个普通的对象,因此注入到IOC容器后,也只是一个普通的bean,并没有任何增强
问题修复
方案一、不使用registerSingleton()
而是使用BeanDefinition注册方式
这种方式本质是让这个对象完整经历了bean的生命周期
示例:
@Configuration public class HelloServiceConfiguration implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableListableBeanFactory; BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(); AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition(); beanDefinition.setBeanClass(HelloService.class); HelloServiceProperties properties = new HelloServiceProperties(); properties.setBeanName("helloService"); beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0,properties); defaultListableBeanFactory.registerBeanDefinition(properties.getBeanName(),beanDefinition); } }
方案二、使用registerSingleton()
但注入的对象不是用new出来的,而是直接注入AOP代理对象
主要利用AOP的代理api:AnnotationAwareAspectJAutoProxyCreator
示例
@Configuration public class HelloServiceWithProxyConfiguration implements BeanFactoryAware, InitializingBean { private BeanFactory beanFactory; @Autowired private AnnotationAwareAspectJAutoProxyCreator annotationAwareAspectJAutoProxyCreator; @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } @Override public void afterPropertiesSet() throws Exception { DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory)beanFactory; HelloServiceProperties properties = new HelloServiceProperties(); properties.setBeanName("helloService"); HelloService helloServicePrxoy = (HelloService) annotationAwareAspectJAutoProxyCreator.postProcessAfterInitialization(new HelloService(properties), "helloService$$Prxoy"); defaultListableBeanFactory.registerSingleton(properties.getBeanName(),helloServicePrxoy); } }
总结
以上两种方案,建议使用方案一。因为方案一完整经历过bean的生命周期,这就意味着可以获取spring提供的各种增强功能。方案二反而更像是硬编码进去,如果后面要使用spring的其他增强的功能,就还必须调用其他API。不过如果可以确定业务不会使用spring提供的各种扩展功能。方案二也是可以的
以上就是spring动态注册bean AOP失效原理解析的详细内容,更多关于spring AOP失效的资料请关注脚本之家其它相关文章!
相关文章
Java设计模式之抽象工厂模式AbstractFactoryPattern详解
这篇文章主要介绍了Java设计模式之抽象工厂模式AbstractFactoryPattern详解,抽象工厂模式是一种软件开发设计模式,抽象工厂模式提供了一种方式,可以将一组具有同一主题的单独的工厂封装起来,需要的朋友可以参考下2023-10-10详解SpringBoot中异步请求和异步调用(看完这一篇就够了)
这篇文章主要介绍了SpringBoot中异步请求和异步调用问题,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下2019-04-04解决Spring session(redis存储方式)监听导致创建大量redisMessageListenerConta
这篇文章主要介绍了解决Spring session(redis存储方式)监听导致创建大量redisMessageListenerContailner-X线程问题,需要的朋友可以参考下2018-08-08
最新评论