spring動(dòng)態(tài)注冊(cè)bean?AOP失效原理解析
前言
本文的素材來(lái)自讀者的一個(gè)問(wèn)題,他看過(guò)我之前寫的一篇博文聊聊如何把第三方服務(wù)注冊(cè)到我們項(xiàng)目的spring容器中。剛好他項(xiàng)目中也有類似這樣的一個(gè)需求,他就采用我文中介紹的第三種方法
調(diào)用beanFactory.registerSingleton()
一開始項(xiàng)目運(yùn)行得還可以,后面他在這個(gè)第三方服務(wù)中使用AOP,發(fā)現(xiàn)AOP始終沒(méi)有生效。于是他就給我留言了。今天就來(lái)聊一下這個(gè)話題,為什么使用registerSingleton()注冊(cè)的bean,無(wú)法使AOP生效
問(wèn)題根源
registerSingleton()這個(gè)方法直接將bean存放到單例池里面了。
如果對(duì)bean的生命周期有了解的朋友,應(yīng)該會(huì)知道,bean可能會(huì)經(jīng)過(guò)一系列的后置處理器后,再存放到單例池里面。因此這個(gè)bean可能是會(huì)被增強(qiáng)的,其中當(dāng)然包括經(jīng)過(guò)AOP增強(qiáng)
而使用registerSingleton()相當(dāng)于是直接走捷徑,不經(jīng)過(guò)后置處理器,一步到位直接存放到單例池中。如果第三方服務(wù)是直接通過(guò)new出來(lái)的,就是一個(gè)普通的對(duì)象,因此注入到IOC容器后,也只是一個(gè)普通的bean,并沒(méi)有任何增強(qiáng)
問(wèn)題修復(fù)
方案一、不使用registerSingleton()
而是使用BeanDefinition注冊(cè)方式
這種方式本質(zhì)是讓這個(gè)對(duì)象完整經(jīng)歷了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()
但注入的對(duì)象不是用new出來(lái)的,而是直接注入AOP代理對(duì)象
主要利用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); } }
總結(jié)
以上兩種方案,建議使用方案一。因?yàn)榉桨敢煌暾?jīng)歷過(guò)bean的生命周期,這就意味著可以獲取spring提供的各種增強(qiáng)功能。方案二反而更像是硬編碼進(jìn)去,如果后面要使用spring的其他增強(qiáng)的功能,就還必須調(diào)用其他API。不過(guò)如果可以確定業(yè)務(wù)不會(huì)使用spring提供的各種擴(kuò)展功能。方案二也是可以的
以上就是spring動(dòng)態(tài)注冊(cè)bean AOP失效原理解析的詳細(xì)內(nèi)容,更多關(guān)于spring AOP失效的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringBoot集成WebSocket實(shí)現(xiàn)前后端消息互傳的方法
這篇文章主要介紹了SpringBoot集成WebSocket實(shí)現(xiàn)前后端消息互傳的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10springboot集成shiro詳細(xì)總結(jié)
這幾天在看 shiro,用 springboot 集成了一下,下面的這個(gè)例子中主要介紹了 shiro 的認(rèn)證和授權(quán),以及鹽值加密的功能.程序可以運(yùn)行起來(lái).這里只做一個(gè)簡(jiǎn)單的介紹,后續(xù)會(huì)針對(duì)各個(gè)功能做一個(gè)詳細(xì)的介紹,這里不做過(guò)多的贅述,需要的朋友可以參考下2021-05-05SpringBoot使用WebJars統(tǒng)一管理靜態(tài)資源的方法
這篇文章主要介紹了SpringBoot使用WebJars統(tǒng)一管理靜態(tài)資源的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-12-12Java使用FileInputStream流讀取文件示例詳解
這篇文章主要介紹了Java使用FileInputStream流讀取文件示例詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07JAVA?IDEA項(xiàng)目打包為jar包的步驟詳解
在Java開發(fā)中我們通常會(huì)將我們的項(xiàng)目打包成可執(zhí)行的Jar包,以便于在其他環(huán)境中部署和運(yùn)行,下面這篇文章主要給大家介紹了關(guān)于JAVA?IDEA項(xiàng)目打包為jar包的相關(guān)資料,需要的朋友可以參考下2024-08-08