前言

本文的素材来自读者的一个问题,他看过我之前写的一篇博文聊聊如何把第三方服务注册到咱们我的项目的spring容器中。刚好他我的项目中也有相似这样的一个需要,他就采纳我文中介绍的第三种办法

调用beanFactory.registerSingleton()

一开始我的项目运行得还能够,前面他在这个第三方服务中应用AOP,发现AOP始终没有失效。于是他就给我留言了。明天就来聊一下这个话题,为什么应用registerSingleton()注册的bean,无奈使AOP失效

问题本源

registerSingleton()这个办法间接将bean寄存到单例池外面了。

如果对bean的生命周期有理解的敌人,应该会晓得,bean可能会通过一系列的后置处理器后,再寄存到单例池外面。因而这个bean可能是会被加强的,其中当然包含通过AOP加强

而应用registerSingleton()相当于是间接走捷径,不通过后置处理器,一步到位间接寄存到单例池中。如果第三方服务是间接通过new进去的,就是一个一般的对象,因而注入到IOC容器后,也只是一个一般的bean,并没有任何加强

问题修复

计划一:不应用registerSingleton(),而是应用BeanDefinition注册形式

这种形式实质是让这个对象残缺经验了bean的生命周期

示例:

@Configurationpublic 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

示例

@Configurationpublic 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提供的各种扩大性能。计划二也是能够的

demo链接

https://github.com/lyb-geek/springboot-learning/tree/master/springboot-registerSingleton-aop-invalid