Springboot源碼分析之EnableAspectJAutoProxy

摘要:

Spring Framwork的兩大核心技術就是IOCAOPAOPSpring的產品線中有着大量的應用。若是說反射是你通向高級的基礎,那麼代理就是你站穩高級的底氣。AOP的本質也就是你們所熟悉的CGLIB動態代理技術,在平常工做中想必或多或少都用過可是它背後的祕密值得咱們去深思。本文主要從Spring AOP運行過程上,結合必定的源碼總體上介紹Spring AOP的一個運行過程。知其然,知其因此然,才能更好的駕馭這門核心技術。spring

@Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import({AspectJAutoProxyRegistrar.class})
    public @interface EnableAspectJAutoProxy {
        //代表該類採用CGLIB代理仍是使用JDK的動態代理
        boolean proxyTargetClass() default false;
         /**
         * @since 4.3.1 代理的暴露方式:解決內部調用不能使用代理的場景  默認爲false表示不處理
         * true:這個代理就能夠經過AopContext.currentProxy()得到這個代理對象的一個副本(ThreadLocal裏面),從而咱們能夠很方便得在Spring框架上下文中拿到當前代理對象(處理事務時很方便)
         * 必須爲true才能調用AopContext得方法,不然報錯:Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available.
         */
        boolean exposeProxy() default false;
    }複製代碼

全部的EnableXXX驅動技術都得看他的@Import,因此上面最重要的是這一句@Import(AspectJAutoProxyRegistrar.class),下面看看它緩存

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
        AspectJAutoProxyRegistrar() {
        }
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            //註冊了一個基於註解的自動代理建立器   AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
            AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
            if (enableAspectJAutoProxy != null) {
                  //表示強制指定了要使用CGLIB
                if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
                    AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
                }
              //強制暴露Bean的代理對象到AopContext
                if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
                    AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
                }
            }
        }
    }複製代碼

AspectJAutoProxyRegistrar是一個項容器註冊自動代理建立器app

@Nullable
        public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
                BeanDefinitionRegistry registry, @Nullable Object source) {
            return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
        }複製代碼

說明spring容器的註解代理建立器就是AnnotationAwareAspectJAutoProxyCreator框架

@Nullable
        private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
            Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
          //這裏若是咱們本身定義了這樣一個自動代理建立器就是用咱們自定義的
            if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {
                BeanDefinition apcDefinition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");
                if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
                    int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
                  /** 
                   *用戶註冊的建立器,必須是InfrastructureAdvisorAutoProxyCreator
                   *AspectJAwareAdvisorAutoProxyCreator,AnnotationAwareAspectJAutoProxyCreator之一
                  */
                    int requiredPriority = findPriorityForClass(cls);
                    if (currentPriority < requiredPriority) {
                        apcDefinition.setBeanClassName(cls.getName());
                    }
                }
                return null;
            } 
          //若用戶本身沒有定義,那就用默認的AnnotationAwareAspectJAutoProxyCreator
          RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
              beanDefinition.setSource(source);
          //此處注意,增長了一個屬性:最高優先級執行,後面會和@Async註解一塊兒使用的時候起關鍵做用
            beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
            beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
            return beanDefinition;
        }複製代碼

咱們就成功的注入了一個BeanAnnotationAwareAspectJAutoProxyCreator 基於註解的自動代理建立器post

Spring中自動建立代理器

file

因而可知,Spring使用BeanPostProcessor讓自動生成代理。基於BeanPostProcessor的自動代理建立器的實現類,將根據一些規則在容器實例化Bean時爲匹配的Bean生成代理實例。ui

AbstractAutoProxyCreator是對自動代理建立器的一個抽象實現。最重要的是,它實現了SmartInstantiationAwareBeanPostProcessor接口,所以會介入到Spring IoC容器Bean實例化的過程。spa

SmartInstantiationAwareBeanPostProcessor繼承InstantiationAwareBeanPostProcessor因此它最主要的 職責是在bean的初始化前,先會執行全部的InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation,誰第一個返回了不爲nullBean,後面就都不會執行了 。而後會再執行BeanPostProcessor#postProcessAfterInitialization scala

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
            Object exposedObject = bean;
            if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
                for (BeanPostProcessor bp : getBeanPostProcessors()) {
                    if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                        SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
                        exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
                    }
                }
            }
            return exposedObject;
        }複製代碼

說明:這個方法是spring的三級緩存中的其中一環,當你調用Object earlySingletonReference = getSingleton(beanName, false);時候就會觸發,其實還有一個地方exposedObject = initializeBean(beanName, exposedObject, mbd);也會觸發致使返回一個代理對象。代理

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                    invokeAwareMethods(beanName, bean);
                    return null;
                }, getAccessControlContext());
            }
            else {
                invokeAwareMethods(beanName, bean);
            }
            Object wrappedBean = bean;
            if (mbd == null || !mbd.isSynthetic()) {
                wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
            }
            try {
                invokeInitMethods(beanName, wrappedBean, mbd);
            }
            catch (Throwable ex) {
                throw new BeanCreationException(
                        (mbd != null ? mbd.getResourceDescription() : null),
                        beanName, "Invocation of init method failed", ex);
            }
            if (mbd == null || !mbd.isSynthetic()) {
                wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
            }
            return wrappedBean;
        }複製代碼

強調: 這2個地方雖然都有後置加強的做用,可是@Async所使用的AsyncAnnotationBeanPostProcessor不是SmartInstantiationAwareBeanPostProcessor的實現類,因此此處會致使@Transactional@Async處理循環依賴時候的不一致性。對於循環依賴後續會有單獨章節進行分享。code

AbstractAdvisorAutoProxyCreator

如何建立代理對象後續文章在進行分析。

相關文章
相關標籤/搜索