SpringAOP源碼跟蹤及學習

Spring 版本 4.3.2java

在拿到 Bean 實例之後,會經歷一系列的初始化工做,如:工廠回調、init 方法、後處理器在 Bean 初始化先後的處理等,在通常狀況下(非 factory-method 建立的 Bean 等),AOP代理對象的建立就在後處理器的處理方法中實現。spring

入口

以 AbstractAutowireCapableBeanFactory 類中的 initializeBean 方法做爲起始點進行跟蹤緩存

/**
* Initialize the given bean instance, applying factory callbacks
* as well as init methods and bean post processors.
* <p>Called from {@link #createBean} for traditionally defined beans,
* and from {@link #initializeBean} for existing bean instances.
*
* 初始化給定的 bean 實例,應用工廠回調方法以及 init 方法和 bean 的後處理器。
* 該方法會被傳統定義 bean 的 createBean 方法所調用,也會被重載方法所引用
*/
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;
}

依然在 AbstractAutowireCapableBeanFactory 類中。app

拿到 BeanFactory 中全部針對 Bean 的後處理器集合,依次調用。ide

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
    throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        
        // 利用處理器的處理方法,對 bean 實例進行處理,並返回一個對象
        Object current = processor.postProcessAfterInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}

註冊建立器

在後處理器集合中,有一個處理器叫作 AnnotationAwareAspectJAutoProxyCreator 建立器,該處理器在解析<aop:config>標籤、或者解析相關注解時被註冊到工廠中,以下:post

// 若是必要的話註冊AspectJ自動代理建立器
public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {

    // 傳遞了 AspectJAwareAdvisorAutoProxyCreator 的 Class,進入這個方法
    return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source);
}


private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");

    //工廠中是否已經註冊了 org.springframework.aop.config.internalAutoProxyCreator
    if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
        BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);

        //若是已經有註冊了 internalAutoProxyCreator,而且和入參傳遞的Class不是同一個Class,
        //那麼就根據優先級進行選擇
        if (!cls.getName().equals(apcDefinition.getBeanClassName())) {

            //類 AopConfigUtils 中有個 ArrayList 屬性 APC_PRIORITY_LIST,在類靜態構造中依次加入了
            //幾個建立器,這個方法就是查找某個建立器在 APC_PRIORITY_LIST 中的索引,若是沒有找到就報錯
            int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
            int requiredPriority = findPriorityForClass(cls);

            // internalAutoProxyCreator 的索引爲0,入參的 AspectJAwareAdvisorAutoProxyCreator
            // 索引爲1,後者要大,因此從新設置下 apcDefinition 的 beanClass
            if (currentPriority < requiredPriority) {
                apcDefinition.setBeanClassName(cls.getName());
            }
        }

        //直接返回null
        return null;
    }
    
    // 若是沒有註冊 internalAutoProxyCreator ,組裝一個 Bean Definition,以 
    // AspectJAwareAdvisorAutoProxyCreator 做爲 bean Class,而後註冊到工廠中
    RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
    beanDefinition.setSource(source);
    beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
    beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
    return beanDefinition;
}

從上面能夠看見建立器 AnnotationAwareAspectJAutoProxyCreator 的註冊通過,Bean Definition 是對 Bean 的描述,建立 bean 對象時,會以 Bean Definition 爲依據進行實例化和初始化。優化

postProcessAfterInitialization

查看建立器的處理方法postProcessAfterInitializationui

該方法在建立器的超類 AbstractAutoProxyCreator 中實現this

/**
* Create a proxy with the configured interceptors if the bean is
* identified as one to proxy by the subclass.
* 
* 若是 bean 被定義爲子類代理,則使用已配置的攔截器建立代理
*/
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (!this.earlyProxyReferences.contains(cacheKey)) {
            
            // 緩存中沒有的狀況
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

/**
* Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
* 
* 必要的話包裝給定的 bean,即,他有資格被代理
*/
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }
    
    // advisedBeans 存放 bean 是否能夠被代理的信息,做爲緩存,避免重複判斷
    // Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<>
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }
    
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        
        // 若是 bean 是一些特殊的類,好比 Pointcut/Advisor,又或者沒有 @Aspect 註解等
        // 這些 bean 不該該被代理,信息存放到 advisedBeans 集合中
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    // Create proxy if we have advice.
    // 若是有通知,建立代理
    
    // 拿到全部匹配該 bean 的通知,若是使用了切入點表達式或者 AspectJ 風格的加強,
    // 還須要在通知鏈的開始處添加 ExposeInvocationInterceptor 攔截器
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    if (specificInterceptors != DO_NOT_PROXY) {
        
        // 通知鏈不爲null,能夠代理
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        
        // 建立代理對象,進入跟蹤
        Object proxy = createProxy(
            bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        
        // 存放已經生成代理對象的類信息
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }

    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}

建立代理

該方法在 AbstractAutoProxyCreator 中實現lua

/**
* Create an AOP proxy for the given bean.
* 
* 爲指定的 bean 建立一個 AOP 代理
*/
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
                             @Nullable Object[] specificInterceptors, TargetSource targetSource) {

    if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
        
        // 在 beanFactory 中,beanName 有對應的 BeanDefinition,此方法就是爲 BeanDefinition 的
        // attributes 屬性添加鍵值對,key 爲 xxx.originalTargetClass , value 包含了 targetSource
        AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
    }

    ProxyFactory proxyFactory = new ProxyFactory();
    
    // 將建立器中的一些屬性拷貝到新建立的代理工廠
    proxyFactory.copyFrom(this);

    // proxyTargetClass 屬性對代理方式的肯定有很是大的影響
    // 當從建立器中拷貝的屬性 proxyFactory 爲 false 時,下面的兩個方法須要詳細跟蹤
    if (!proxyFactory.isProxyTargetClass()) {
        if (shouldProxyTargetClass(beanClass, beanName)) {
            proxyFactory.setProxyTargetClass(true);
        }
        else {
            evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }

    // 對攔截器或者通知進行包裝,包裝成Advisor對象
    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    
    // 在代理工廠中添加 Advisor 通知鏈
    proxyFactory.addAdvisors(advisors);
    proxyFactory.setTargetSource(targetSource);
    
    // 子類中若是沒有覆蓋,那麼此方法爲空實現
    customizeProxyFactory(proxyFactory);

    proxyFactory.setFrozen(this.freezeProxy);
    if (advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }

    // 經過代理工廠獲取代理
    return proxyFactory.getProxy(getProxyClassLoader());
}

proxyTargetClass 布爾屬性值的肯定對代理方式有着很是大的影響。

當配置了<aop:aspectj-autoproxy>,使用註解方式時;又或者是使用xml配置<aop:config>時,兩個標籤都具備的proxy-target-class屬性默認爲 false

那麼上述步驟建立 ProxyFactory 對象時,從建立器中拷貝的 proxyTargetClass 屬性則爲 false,進入條件

if (!proxyFactory.isProxyTargetClass()) {
    if (shouldProxyTargetClass(beanClass, beanName)) {
        proxyFactory.setProxyTargetClass(true);
    }
    else {
        evaluateProxyInterfaces(beanClass, proxyFactory);
    }
}

先看第一個方法shouldProxyTargetClass

shouldProxyTargetClass

該方法在 AbstractAutoProxyCreator 中實現

/**
* Determine whether the given bean should be proxied with its target class rather than its interfaces.
* <p>Checks the {@link AutoProxyUtils#PRESERVE_TARGET_CLASS_ATTRIBUTE "preserveTargetClass" attribute}
* of the corresponding bean definition.
* 
* 肯定給定的bean是否應該使用其目標類而不是其接口進行代理。
* 檢查對應 bean definition 的 preserveTargetClass 屬性。
*/
protected boolean shouldProxyTargetClass(Class<?> beanClass, String beanName) {
    
    return (this.beanFactory instanceof ConfigurableListableBeanFactory &&
            AutoProxyUtils.shouldProxyTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName));
    
}

工廠默認實現 DefaultListableBeanFactory 類實現了 ConfigurableListableBeanFactory 接口。

跟蹤 AutoProxyUtils 類的 shouldProxyTargetClass 方法。

public static boolean shouldProxyTargetClass(ConfigurableListableBeanFactory beanFactory, String beanName) {
    
    // 工廠中有對應 beanName 的 bean definition 則進入條件
    if (beanName != null && beanFactory.containsBeanDefinition(beanName)) {
        BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
        
        // bean definition 的 attributes 屬性中是否有
        // org.springframework.aop.framework.autoproxy.AutoProxyUtils.preserveTargetClass
        // 爲 key 的屬性,且 value 爲 ture
        return Boolean.TRUE.equals(bd.getAttribute(PRESERVE_TARGET_CLASS_ATTRIBUTE));
    }
    return false;
}

若是被代理 bean 對應的 bean definition 屬性中,存在org.springframework.aop.framework.autoproxy.AutoProxyUtils.preserveTargetClass爲 key,且 值爲 true 的 attributes

那麼設置 proxyTargetClass 爲 ture

再看第二個方法

evaluateProxyInterfaces

該方法在類 ProxyProcessorSupport 中實現,ProxyProcessorSupport 是 AbstractAutoProxyCreator 的父類

/**
* Check the interfaces on the given bean class and apply them to the {@link ProxyFactory},
* if appropriate.
* <p>Calls {@link #isConfigurationCallbackInterface} and {@link #isInternalLanguageInterface}
* to filter for reasonable proxy interfaces, falling back to a target-class proxy otherwise.
* 
* 檢查指定 bean class 上的接口,若是合適的話設置到 ProxyFactory 中。
* 調用 isConfigurationCallbackInterface 方法和 isInternalLanguageInterface 方法去過濾獲得
* 合理的代理接口,不然回退到 target-class proxy
*/
protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
    
    // 此方法拿到類上及其父類上,全部的接口,不會遞歸獲取接口上的接口
    Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
    boolean hasReasonableProxyInterface = false;
    
    // 遍歷全部的接口,並進行過濾
    for (Class<?> ifc : targetInterfaces) {
        
        // 接口中不能有像 Aware、InitializingBean 等容器的回調接口
        // 接口的 ClassName 也不能是以 .cglib.proxy.Factory 結尾或者是 groovy.lang.GroovyObject
        // 這樣的內部語言接口
        if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
            ifc.getMethods().length > 0) {
            
            // 若是還有接口剩餘,則存在合適的代理接口
            hasReasonableProxyInterface = true;
            break;
        }
    }
    if (hasReasonableProxyInterface) {
        
        // 將代理接口一個個添加到 proxyFactory 中
        for (Class<?> ifc : targetInterfaces) {
            proxyFactory.addInterface(ifc);
        }
    }
    else {
        
        // 否者 proxyTargetClass 屬性設置爲 true
        proxyFactory.setProxyTargetClass(true);
    }
}

總結一下兩個方法

當 xml 中沒有配置 proxyTargetClass 屬性,默認爲 false

若是被代理 bean 對應的 bean definition ,它的 attributes 屬性中,存在org.springframework.aop.framework.autoproxy.AutoProxyUtils.preserveTargetClass爲 key,值爲 true 的鍵值對

那麼設置 proxyTargetClass 爲 ture

不然過濾全部接口,接口不能爲 Aware、InitializingBean 等容器的回調接口,也不能是內部語言接口

若是沒有合適的接口,proxyTargetClass 仍是設置爲 true 。

接下來看下代理工廠獲取代理的流程。

getProxy

進入 ProxyFactory 類中,跟蹤 getProxy 方法

/**
* Create a new proxy according to the settings in this factory.
* <p>Can be called repeatedly. Effect will vary if we've added
* or removed interfaces. Can add and remove interceptors.
* <p>Uses the given class loader (if necessary for proxy creation).
*
* 根據這個 factory 的設置建立一個新的代理。
* 能夠被重複調用。若是咱們添加或者移除了接口,會有影響。
* 能夠添加和移除攔截器。
* 使用指定的類加載器(若是須要代理建立)
*/
public Object getProxy(@Nullable ClassLoader classLoader) {
    return createAopProxy().getProxy(classLoader);
}

先跟蹤 createAopProxy 方法,此方法在 ProxyCreatorSupport 類中實現,ProxyFactory 是其子類。

/**
* Subclasses should call this to get a new AOP proxy. They should <b>not</b>
* create an AOP proxy with {@code this} as an argument.
*
* 子類應該調用這個方法去得到一個新的AOP代理。他們不該該用 this 做爲參數建立一個AOP代理
*/
protected final synchronized AopProxy createAopProxy() {
    
    // 當AOP代理第一次被建立時,active會被設置爲true
    if (!this.active) {
        
        // 設置 active 爲 true,激活代理配置
        activate();
    }
    return getAopProxyFactory().createAopProxy(this);
}

getAopProxyFactory 方法拿到的是 DefaultAopProxyFactory 的實例,它的接口是 AopProxyFactory

ProxyFactory 類間接繼承 AdvisedSupport ,AdvisedSupport 繼承 ProxyConfig ,做爲配置存在

ProxyFactory 類和 DefaultAopProxyFactory 並無繼承關係

以 ProxyFactory 類的實例爲參數,調用 createAopProxy 方法,繼續跟蹤

createAopProxy

此方法在 DefaultAopProxyFactory 類中實現,採用 JDK proxy 代理仍是使用 cglib 代理,在這個方法中決定

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
        Class<?> targetClass = config.getTargetClass();
        if (targetClass == null) {
            throw new AopConfigException("TargetSource cannot determine target class: " +
                                         "Either an interface or a target is required for proxy creation.");
        }
        if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
            return new JdkDynamicAopProxy(config);
        }
        return new ObjenesisCglibAopProxy(config);
    }
    else {
        return new JdkDynamicAopProxy(config);
    }
}

isOptimize 方法就是返回 ProxyFactory 的 optimize 屬性,爲布爾值

是否執行積極優化的含義。

優化一般意味着,在代理建立後,通知的變化不會帶來影響,默認下爲 false。

optimize 在此處也被做爲了一個判斷依據。

optimize 能夠參考文章:https://blog.csdn.net/zh199609/article/details/79710846

isProxyTargetClass 方法拿的則是 ProxyFactory 的 proxyTargetClass 屬性,前面已經跟蹤過。

hasNoUserSuppliedProxyInterfaces 方法在代理接口不存在,或者只有一個且是 SpringProxy 接口的子接口狀況下,才返回 true 。

當上述三個方法都返回 false 時,代理才走的 JDK proxy 代理,也就是接口代理。

當知足其中一個條件,進入方法後,還有一層篩選,要麼 target Class 是一個接口,要麼是 Proxy 類的子類,不然其他狀況都使用 cglib 代理,也就是類代理。

最後調用代理的 getProxy 方法。不一樣代理的實現,其實就是spring對 JDK 的 Proxy,或者 cglib 的 Enhancer 的封裝。最終完成AOP的實現。

相關文章
相關標籤/搜索