Spring
的代理在上層中主要分爲ProxyCreatorSupport
和ProxyProcessorSupport
,前者是基於代理工廠,後者是基於後置處理器,也能夠認爲後置就是自動代理器。當spring
容器中須要進行aop
進行織入的bean
較多時,簡單採用ProxyFacotryBean
無疑會增長不少工做量(由於每一個Bean
!都得手動寫一個)。因此自動代理就發揮它的做用了。java
在內部,Spring使用BeanPostProcessor
讓自動生成代理。基於BeanPostProcessor的自動代理建立器的實現類,將根據一些規則在容器實例化Bean
時爲匹配的Bean生成代理實例。代理建立器能夠分爲三類:git
BeanNameAutoProxyCreator
Advisor
匹配機制的自動代理建立器它會對容器中的全部Advisor進行掃描,自動將這些切面應用到匹配的Bean中,實現類是DefaultAdvisorAutoProxyCreator
(它也支持前綴匹配) AspectJ
註解的自動代理生成器:爲包含AspectJ註解的切入的Bean自動建立代理實例,實現類是AnnotationAwareAspectJAutoProxyCreator
,它是咱們的@EnableAspectJAutoProxy
導入的,這也是咱們當下使用最爲普遍的方式~ 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
默認給你註冊的自動建立器AnnotationAwareAspectJAutoProxyCreator
,那麼你能夠註冊一個Bean名稱以下的Bean便可:github
// 手動註冊一個自動代理建立器,且名字務必叫AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME
@Bean(AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME)
public BeanNameAutoProxyCreator beanNameAutoProxyCreator() {
...
}複製代碼
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
...
}複製代碼
AbstractAutoProxyCreator
是對自動代理建立器的一個抽象實現。最重要的是,它實現了SmartInstantiationAwareBeanPostProcessor
接口,所以會介入到Spring IoC
容器Bean實例化的過程,在AbstractAutowireCapableBeanFactory
中有這樣一段代碼spring
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;
}
}複製代碼
可是通常都不會生效的,由於這個resolveBeforeInstantiation
只是針對有自定義的targetsource
,由於自定義的targetsource
不是spring的bean那麼確定不須要進行後續的一系列的實例化 初始化。因此能夠在resolveBeforeInstantiation直接進行proxy
。簡單的說吧 ,這個代碼能夠忽略不計,開發者通常用不到。springboot
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
第一次後置處理器的使用,若是這樣直接就返回了,就至關於脫離了IOC
的生命週期了同樣,依賴注入,屬性填充等這些都沒有進行處理,因此使用的時候必定要注意,最好別使用這個功能。架構
在初始化bean的過程當中後續還有2個特別重要的後置處理過程,對於循環依賴甚至異步註解事物註解等都有或多或少的影響,後續會繼續分析它們。異步
SpringAOP
應儘可能避免本身建立AutoProxyCreator
,內部機制及其複雜不免會因爲沒有想到的問題而出現其餘不常見的問題,上面分享的內容不多,緣由是我以爲熟悉這個架構設計師最關鍵的,各類子類的雖然實現大不相同,可是你想所有都記在腦海或者很熟悉那是不太現實的,只有熟悉他的設計才能碰見問題輕易的就能翻源碼解決。ide