Springboot源碼 AbstractAdvisorAutoProxyCreator解析
摘要:
Spring的代理在上層中主要分為ProxyCreatorSupport
和ProxyProcessorSupport
,前者是基于代理工廠,后者是基于后置處理器,也可以認(rèn)為后置就是自動代理器。當(dāng)spring容器中需要進(jìn)行aop
進(jìn)行織入的bean較多時,簡單采用ProxyFacotryBean
無疑會增加很多工作量(因?yàn)槊總€Bean
!都得手動寫一個)。所以自動代理就發(fā)揮它的作用了。
Spring中自動創(chuàng)建代理器分類
在內(nèi)部,Spring使用BeanPostProcessor
讓自動生成代理?;?code>BeanPostProcessor的自動代理創(chuàng)建器的實(shí)現(xiàn)類,將根據(jù)一些規(guī)則在容器實(shí)例化Bean時為匹配的Bean
生成代理實(shí)例。代理創(chuàng)建器可以分為三類:
- 基于Bean配置名規(guī)則的自動代理生成器:允許為一組特定配置名的Bean自動創(chuàng)建代理實(shí)例的代理創(chuàng)建器,實(shí)現(xiàn)類為
BeanNameAutoProxyCreator
- 基于Advisor匹配機(jī)制的自動代理創(chuàng)建器它會對容器中的所有Advisor進(jìn)行掃描,自動將這些切面應(yīng)用到匹配的Bean中,實(shí)現(xiàn)類是
DefaultAdvisorAutoProxyCreator
(它也支持前綴匹配) - 基于Bean中AspectJ注解的自動代理生成器:為包含AspectJ注解的切入的Bean自動創(chuàng)建代理實(shí)例,實(shí)現(xiàn)類是
AnnotationAwareAspectJAutoProxyCreator
,它是我們的@EnableAspectJAutoProxy
導(dǎo)入的,這也是我們當(dāng)下使用最為廣泛的方式~
BeanNameAutoProxyCreator
package com.github.dqqzj.springboot.aop; import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; /** * @author qinzhongjian * @date created in 2019-08-25 09:43 * @description: TODO * @since JDK 1.8.0_212-b10 */ @Component public class MyBeanNameAutoProxyCreator extends BeanNameAutoProxyCreator { @PostConstruct public void init() { super.setBeanNames("aopService", "abstractAutoProxyCreatorService"); super.setInterceptorNames("myMethodBeforeAdvice"); } }
如果你想用自己注冊的@Bean
代替@EnableAspectJAutoProxy
默認(rèn)給你注冊的自動創(chuàng)建器AnnotationAwareAspectJAutoProxyCreator
,那么你可以注冊一個Bean名稱如下的Bean即可:
// 手動注冊一個自動代理創(chuàng)建器,且名字務(wù)必叫AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME @Bean(AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME) public BeanNameAutoProxyCreator beanNameAutoProxyCreator() { ... }
AbstractAutoProxyCreator
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware { ... }
AbstractAutoProxyCreator
是對自動代理創(chuàng)建器的一個抽象實(shí)現(xiàn)。最重要的是,它實(shí)現(xiàn)了SmartInstantiationAwareBeanPostProcessor
接口,因此會介入到Spring IoC容器Bean實(shí)例化的過程,在AbstractAutowireCapableBeanFactory
中有這樣一段代碼
try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } }
但是一般都不會生效的,因?yàn)檫@個resolveBeforeInstantiation
只是針對有自定義的targetsource
,因?yàn)樽远x的targetsource不是spring的bean那么肯定不需要進(jìn)行后續(xù)的一系列的實(shí)例化 初始化。所以可以在resolveBeforeInstantiation
直接進(jìn)行proxy。簡單的說吧 ,這個代碼可以忽略不計(jì),開發(fā)者一般用不到。
如何讓resolveBeforeInstantiation直接返回bean?
package com.github.dqqzj.springboot.aop; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor; /** * @author qinzhongjian * @date created in 2019-08-25 11:35 * @description: TODO * @since JDK 1.8.0_212-b10 */ public class AopServiceInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor { @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { if (beanClass.isInstance(AopService.class)) { return new AopService(); } return null; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } }
這個是spring第一次后置處理器的使用,如果這樣直接就返回了,就相當(dāng)于脫離了IOC的生命周期了一樣,依賴注入,屬性填充等這些都沒有進(jìn)行處理,所以使用的時候一定要注意,最好別使用這個功能。
在初始化bean的過程中后續(xù)還有2個特別重要的后置處理過程,對于循環(huán)依賴甚至異步注解事物注解等都有或多或少的影響,后續(xù)會繼續(xù)分析它們。
小結(jié):
SpringAOP
應(yīng)盡量避免自己創(chuàng)建AutoProxyCreator
,內(nèi)部機(jī)制及其復(fù)雜難免會由于沒有想到的問題而出現(xiàn)其他不常見的問題,上面分享的內(nèi)容很少,原因是我覺得熟悉這個架構(gòu)設(shè)計(jì)師最關(guān)鍵的,各種子類的雖然實(shí)現(xiàn)大不相同,但是你想全部都記在腦?;蛘吆苁煜つ鞘遣惶F(xiàn)實(shí)的,只有熟悉他的設(shè)計(jì)才能遇見問題輕易的就能翻源碼解決。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot實(shí)現(xiàn)接口等冪次校驗(yàn)的示例代碼
本文主要介紹了SpringBoot實(shí)現(xiàn)接口等冪次校驗(yàn)的示例代碼,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-01-01簡單學(xué)習(xí)Java抽象類要點(diǎn)及實(shí)例
這篇文章主要介紹了Java抽象類要點(diǎn)及實(shí)例,有需要的朋友可以參考一下2014-01-01Java動態(tài)代理靜態(tài)代理實(shí)例分析
這篇文章主要介紹了Java動態(tài)代理靜態(tài)代理實(shí)例分析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-03-03如何把char數(shù)組轉(zhuǎn)換成String
這篇文章主要介紹了如何把char數(shù)組轉(zhuǎn)換成String問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02SpringBoot實(shí)現(xiàn)統(tǒng)一功能處理的教程詳解
這篇文章主要為大家詳細(xì)介紹了SpringBoot如何實(shí)現(xiàn)統(tǒng)一功能處理,文中的示例代碼講解詳細(xì),對大家學(xué)習(xí)或工作有一定借鑒價值,感興趣的同學(xué)可以參考閱讀下2023-05-05