Springboot源碼 AbstractAdvisorAutoProxyCreator解析
摘要:
Spring的代理在上層中主要分為ProxyCreatorSupport和ProxyProcessorSupport,前者是基于代理工廠,后者是基于后置處理器,也可以認(rèn)為后置就是自動(dòng)代理器。當(dāng)spring容器中需要進(jìn)行aop進(jìn)行織入的bean較多時(shí),簡單采用ProxyFacotryBean無疑會(huì)增加很多工作量(因?yàn)槊總€(gè)Bean!都得手動(dòng)寫一個(gè))。所以自動(dòng)代理就發(fā)揮它的作用了。

Spring中自動(dòng)創(chuàng)建代理器分類
在內(nèi)部,Spring使用BeanPostProcessor讓自動(dòng)生成代理。基于BeanPostProcessor的自動(dòng)代理創(chuàng)建器的實(shí)現(xiàn)類,將根據(jù)一些規(guī)則在容器實(shí)例化Bean時(shí)為匹配的Bean生成代理實(shí)例。代理創(chuàng)建器可以分為三類:
- 基于Bean配置名規(guī)則的自動(dòng)代理生成器:允許為一組特定配置名的Bean自動(dòng)創(chuàng)建代理實(shí)例的代理創(chuàng)建器,實(shí)現(xiàn)類為
BeanNameAutoProxyCreator - 基于Advisor匹配機(jī)制的自動(dòng)代理創(chuàng)建器它會(huì)對(duì)容器中的所有Advisor進(jìn)行掃描,自動(dòng)將這些切面應(yīng)用到匹配的Bean中,實(shí)現(xiàn)類是
DefaultAdvisorAutoProxyCreator(它也支持前綴匹配) - 基于Bean中AspectJ注解的自動(dòng)代理生成器:為包含AspectJ注解的切入的Bean自動(dòng)創(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");
}
}

如果你想用自己注冊(cè)的@Bean代替@EnableAspectJAutoProxy默認(rèn)給你注冊(cè)的自動(dòng)創(chuàng)建器AnnotationAwareAspectJAutoProxyCreator,那么你可以注冊(cè)一個(gè)Bean名稱如下的Bean即可:
// 手動(dòng)注冊(cè)一個(gè)自動(dòng)代理創(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是對(duì)自動(dòng)代理創(chuàng)建器的一個(gè)抽象實(shí)現(xiàn)。最重要的是,它實(shí)現(xiàn)了SmartInstantiationAwareBeanPostProcessor接口,因此會(huì)介入到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;
}
}
但是一般都不會(huì)生效的,因?yàn)檫@個(gè)resolveBeforeInstantiation只是針對(duì)有自定義的targetsource,因?yàn)樽远x的targetsource不是spring的bean那么肯定不需要進(jìn)行后續(xù)的一系列的實(shí)例化 初始化。所以可以在resolveBeforeInstantiation直接進(jìn)行proxy。簡單的說吧 ,這個(gè)代碼可以忽略不計(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;
}
}

這個(gè)是spring第一次后置處理器的使用,如果這樣直接就返回了,就相當(dāng)于脫離了IOC的生命周期了一樣,依賴注入,屬性填充等這些都沒有進(jìn)行處理,所以使用的時(shí)候一定要注意,最好別使用這個(gè)功能。
在初始化bean的過程中后續(xù)還有2個(gè)特別重要的后置處理過程,對(duì)于循環(huán)依賴甚至異步注解事物注解等都有或多或少的影響,后續(xù)會(huì)繼續(xù)分析它們。
小結(jié):
SpringAOP應(yīng)盡量避免自己創(chuàng)建AutoProxyCreator,內(nèi)部機(jī)制及其復(fù)雜難免會(huì)由于沒有想到的問題而出現(xiàn)其他不常見的問題,上面分享的內(nèi)容很少,原因是我覺得熟悉這個(gè)架構(gòu)設(shè)計(jì)師最關(guān)鍵的,各種子類的雖然實(shí)現(xiàn)大不相同,但是你想全部都記在腦?;蛘吆苁煜つ鞘遣惶F(xiàn)實(shí)的,只有熟悉他的設(shè)計(jì)才能遇見問題輕易的就能翻源碼解決。
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java中的stream流的概念解析及實(shí)際運(yùn)用總結(jié)
流是指傳輸時(shí)的數(shù)據(jù),Java為流準(zhǔn)備了很多內(nèi)置類,尤其是IO輸入輸出流非常常用,這里我們來看一下Java中的stream流的概念解析及實(shí)際運(yùn)用總結(jié)2016-06-06
Java中的可變參數(shù)常見用法實(shí)例總結(jié)
這篇文章主要介紹了Java中的可變參數(shù)常見用法,結(jié)合實(shí)例形式總結(jié)分析了java可變參數(shù)的常見功能、使用方法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2019-10-10
EasyExcel實(shí)現(xiàn)導(dǎo)入+各種數(shù)據(jù)校驗(yàn)功能
這篇文章主要介紹了EasyExcel實(shí)現(xiàn)導(dǎo)入+各種數(shù)據(jù)校驗(yàn),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-05-05
JSP服務(wù)器端和前端出現(xiàn)亂碼問題解決方案
這篇文章主要介紹了JSP服務(wù)器端和前端出現(xiàn)亂碼問題解決方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02
詳解Spring Cloud 跨服務(wù)數(shù)據(jù)聚合框架
這篇文章主要介紹了詳解Spring Cloud 跨服務(wù)數(shù)據(jù)聚合框架,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-03-03
IntelliJ?IDEA?2022.2?正式發(fā)布新功能體驗(yàn)
IntelliJ?IDEA?2022.2為遠(yuǎn)程開發(fā)功能帶來了多項(xiàng)質(zhì)量改進(jìn),使其更美觀、更穩(wěn)定,新版本還具有多項(xiàng)值得注意的升級(jí)和改進(jìn),下面跟隨小編一起看看IDEA?2022.2新版本吧2022-08-08

