Springboot源碼分析之AbstractAdvisorAutoProxyCreator

摘要:

Spring的代理在上層中主要分爲ProxyCreatorSupportProxyProcessorSupport,前者是基於代理工廠,後者是基於後置處理器,也能夠認爲後置就是自動代理器。當spring容器中須要進行aop進行織入的bean較多時,簡單採用ProxyFacotryBean無疑會增長不少工做量(由於每一個Bean!都得手動寫一個)。因此自動代理就發揮它的做用了。java

file

Spring中自動建立代理器分類

在內部,Spring使用BeanPostProcessor讓自動生成代理。基於BeanPostProcessor的自動代理建立器的實現類,將根據一些規則在容器實例化Bean時爲匹配的Bean生成代理實例。代理建立器能夠分爲三類:git

  • 基於Bean配置名規則的自動代理生成器:容許爲一組特定配置名的Bean自動建立代理實例的代理建立器,實現類爲BeanNameAutoProxyCreator
  • 基於Advisor匹配機制的自動代理建立器它會對容器中的全部Advisor進行掃描,自動將這些切面應用到匹配的Bean中,實現類是DefaultAdvisorAutoProxyCreator(它也支持前綴匹配)
  • 基於Bean中AspectJ註解的自動代理生成器:爲包含AspectJ註解的切入的Bean自動建立代理實例,實現類是AnnotationAwareAspectJAutoProxyCreator,它是咱們的@EnableAspectJAutoProxy導入的,這也是咱們當下使用最爲普遍的方式~

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");
        }
    
    }複製代碼

file

若是你想用本身註冊的@Bean代替@EnableAspectJAutoProxy默認給你註冊的自動建立器AnnotationAwareAspectJAutoProxyCreator,那麼你能夠註冊一個Bean名稱以下的Bean便可:github

// 手動註冊一個自動代理建立器,且名字務必叫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是對自動代理建立器的一個抽象實現。最重要的是,它實現了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

如何讓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;
        }
    }複製代碼

file

這個是spring第一次後置處理器的使用,若是這樣直接就返回了,就至關於脫離了IOC的生命週期了同樣,依賴注入,屬性填充等這些都沒有進行處理,因此使用的時候必定要注意,最好別使用這個功能。架構

在初始化bean的過程當中後續還有2個特別重要的後置處理過程,對於循環依賴甚至異步註解事物註解等都有或多或少的影響,後續會繼續分析它們。異步

小結:

SpringAOP應儘可能避免本身建立AutoProxyCreator,內部機制及其複雜不免會因爲沒有想到的問題而出現其餘不常見的問題,上面分享的內容不多,緣由是我以爲熟悉這個架構設計師最關鍵的,各類子類的雖然實現大不相同,可是你想所有都記在腦海或者很熟悉那是不太現實的,只有熟悉他的設計才能碰見問題輕易的就能翻源碼解決。ide

相關文章
相關標籤/搜索