Spring AOP源碼分析(三):基於JDK動態代理和CGLIB建立代理對象的實現原理

AOP代理對象的建立spring

AOP相關的代理對象的建立主要在applyBeanPostProcessorsBeforeInstantiation方法實現:緩存

protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
    for (BeanPostProcessor bp : getBeanPostProcessors()) {

        // 查找實現了InstantiationAwareBeanPostProcessor接口的BeanPostProcessor
        // 其中在spring-aop模塊定義的AspectJAwareAdvisorAutoProxyCreator就實現了InstantiationAwareBeanPostProcessor接口
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            
            // 調用postProcessBeforeInstantiation方法建立對象result
            Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
            
            // 若是建立成功則直接返回
            if (result != null) {
                return result;
            }
        }
    }
    return null;
}
核心實現爲:獲取全部的BeanPostProcessor,而後遍歷查看是否爲子接口InstantiationAwareBeanPostProcessor,若是是則調用其postProcessBeforeInstantiation方法。

AOP代理對象建立器:AspectJAwareAdvisorAutoProxyCreator

InstantiationAwareBeanPostProcessor接口是BeanPostProcessor接口的子接口,主要做用以下英文所示:即主要用於爲特殊定製目標bean的實例化過程,如給目標對象建立代理對象。
Typically used to suppress default instantiation for specific target beans,
for example to create proxies with special TargetSources (pooling targets,
lazily initializing targets, etc), or to implement additional injection strategies
such as field injection.

This interface is a special purpose interface, mainly for internal use within the framework
在spring-aop的配置解析的分析可知:Spring AOP源碼分析(二):AOP的三種配置方式與內部解析實現
,在解析spring的XML配置文件applicationContext.xml的aop:config或aop:aspect-autoproxy標籤時,會建立並註冊AspectJAwareAdvisorAutoProxyCreator(aop:aspect-autoproxy對應的AnnotationAwareAspectJAutoProxyCreator爲AspectJAwareAdvisorAutoProxyCreator子類)這個BeanPostProcessor到spring容器。

AspectJAwareAdvisorAutoProxyCreator的類繼承體系結構中,實現了InstantiationAwareBeanPostProcessor接口,具體爲在抽象父類AbstractAutoProxyCreator:同時定義了postProcessBeforeInstantiation方法的實現。
// 提供爲給定的bean對象建立對應的代理對象的方法實現
// 同時提供代理對象須要的方法攔截器的建立,其中攔截器包括全部代理對象公用的攔截器和某個代理對象私有的攔截器
@SuppressWarnings("serial")
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport 
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
    
    ...
    
    // 在bean對象實例的建立過程當中,在建立bean對象實例以前,先調用這個方法,看是否須要建立一個AOP代理對象直接返回
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
        Object cacheKey = getCacheKey(beanClass, beanName);

        // 返回null,則表示不是AOP的目標對象,不須要建立代理對象
        if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
            if (this.advisedBeans.containsKey(cacheKey)) {
                return null;
            }
            if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return null;
            }
        }

        // Create proxy here if we have a custom TargetSource.
        // Suppresses unnecessary default instantiation of the target bean:
        // The TargetSource will handle target instances in a custom fashion.
        TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
        if (targetSource != null) {
            if (StringUtils.hasLength(beanName)) {
                this.targetSourcedBeans.add(beanName);
            }

            // specificInterceptors類型爲Advisor[],是當前bean須要的輔助功能列表
            // 由於Advisor集成了pointcut和advice,故能夠知道當前bean是否在pointcut攔截範圍內,
            // 若是在獲取配置對應的advice列表,該列表做爲代理對象的interceptor方法攔截器
            // getAdvicesAndAdvisorsForBean由子類實現
            Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);

            // 基於以上輔助功能列表,建立該bean對應的代理對象proxy
            Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
            this.proxyTypes.put(cacheKey, proxy.getClass());

            // 只有建立了proxy,纔不返回null
            return proxy;
        }

        return null;
    }
    
    ...
    
}
postProcessBeforeInstantiation方法的核心邏輯爲:經過在spring-aop配置解析時建立的advisors來爲該目標bean查找對應的輔助方法advices,其中advisor爲集成了pointcut和advice。這些輔助方法advices做爲代理對象的方法攔截器列表specificInterceptors,即代理對象攔截目標對象的方法執行,而後在方法執行先後能夠執行該方法攔截器列表對應的方法,從而爲目標對象的方法添加這些輔助功能。

建立代理對象:createProxy

createProxy的定義以下:代理對象能夠基於JDK的動態代理或者基於CGLIB來建立,其中默認爲基於JDK的動態代理,若是aop:config的proxy-target-class屬性爲true或者目標類沒有實現接口,則使用CGLIB來建立代理對象。
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
        @Nullable Object[] specificInterceptors, TargetSource targetSource) {

    if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
        AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
    }

    // 每一個bean對象都使用一個單例的ProxyFactory來建立代理對象,由於每一個bean須要的輔助方法不同,
    // 而後將該ProxyFactory對象引用做爲構造函數參數建立對應的代理對象
    ProxyFactory proxyFactory = new ProxyFactory();
    proxyFactory.copyFrom(this);

    // 檢查是否配置了<aop:config />節點的proxy-target-class屬性爲true
    if (!proxyFactory.isProxyTargetClass()) {
        if (shouldProxyTargetClass(beanClass, beanName)) {
            proxyFactory.setProxyTargetClass(true);
        }
        else {
            evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }

    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);

    // 爲該代理工廠添加輔助功能包裝器Advisors,結合Advisors來生成代理對象的方法攔截器
    proxyFactory.addAdvisors(advisors);

    // 目標類
    proxyFactory.setTargetSource(targetSource);
    customizeProxyFactory(proxyFactory);

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

    // 爲目標類建立代理對象,若是配置了aop:config的proxy-target-class爲true,則使用CGLIB
    // 不然若是目標類爲接口則使用JDK代理,不然使用CGLIB
    return proxyFactory.getProxy(getProxyClassLoader());
}
JDK動態代理

基於接口實現,經過實現目標類所包含的接口的方法來實現代理,即返回的代理對象爲接口的實現類。因爲是基於JDK的動態代理實現,即實現了JDK提供的InvocationHandler接口,故在運行時在invoke方法攔截目標類對應被代理的接口的全部方法的執行:獲取當前執行的方法對應的方法攔截器鏈,而後經過反射執行該方法時,在方法執行先後執行對應的方法攔截器。
// JDK的動態代理是基於接口的,故只能代理接口中定義的方法。
// 該類須要經過代理工廠,具體爲繼承了AdvisedSupport的代理工廠來建立,而不是直接建立,
// 由於AdvisedSupport提供了AOP的相關配置信息,如Advisors列表等。
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
    
    ...
    
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        MethodInvocation invocation;
        Object oldProxy = null;
        boolean setProxyContext = false;

        TargetSource targetSource = this.advised.targetSource;
        Object target = null;

        try {
        
            ...
            
            Object retVal;

            if (this.advised.exposeProxy) {
                // Make invocation available if necessary.
                oldProxy = AopContext.setCurrentProxy(proxy);
                setProxyContext = true;
            }

            // Get as late as possible to minimize the time we "own" the target,
            // in case it comes from a pool.
            target = targetSource.getTarget();
            Class<?> targetClass = (target != null ? target.getClass() : null);

            // 獲取該方法對應的方法攔截器列表
            // 實現:經過該方法所在類對應的Advisors,獲取該方法的輔助功能Advices列表,即方法攔截器列表。這裏的實現爲懶加載,
            // 即當方法第一次調用的時候才建立該方法攔截器列表,而後使用一個ConcurrentHashMap緩存起來,以後的方法調用直接使用。

            // 其中advised就是該方法的所在bean對應的ProxyFactory對象引用,經過ProxyFactory來建立AopProxy,即當前類對象實例。

            // Get the interception chain for this method.
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

            // Check whether we have any advice. If we don't, we can fallback on direct
            // reflective invocation of the target, and avoid creating a MethodInvocation.

            // 當前執行的方法不包括方法攔截器,即不須要額外的輔助功能,則能夠直接執行
            if (chain.isEmpty()) {
                // We can skip creating a MethodInvocation: just invoke the target directly
                // Note that the final invoker must be an InvokerInterceptor so we know it does
                // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
                Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
            }
            else {
                // 若是當前方法包括方法攔截器,即在執行時須要其餘額外的輔助功能,則建立ReflectiveMethodInvocation
                // We need to create a method invocation...
                invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                // Proceed to the joinpoint through the interceptor chain.
                retVal = invocation.proceed();
            }

            // Massage return value if necessary.
            Class<?> returnType = method.getReturnType();
            if (retVal != null && retVal == target &&
                    returnType != Object.class && returnType.isInstance(proxy) &&
                    !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
                // Special case: it returned "this" and the return type of the method
                // is type-compatible. Note that we can't help if the target sets
                // a reference to itself in another returned object.
                retVal = proxy;
            }
            else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
                throw new AopInvocationException(
                        "Null return value from advice does not match primitive return type for: " + method);
            }
            return retVal;
        }
        ...
    }

    ...
    
}
CGLIB代理
  • 建立目標類的子類來實現代理,代理攔截的只能是目標類的public和protected方法。核心方法爲getProxy即建立代理對象,在這裏織入了輔助功能。app

// 基於類的代理,具體實現爲經過建立目標類的子類來實現代理,即代理對象對應的類爲目標類的子類。
// 因此目標類的須要被代理的方法不能爲final,由於子類沒法重寫final的方法;同時被代理的方法須要是public或者protected,不能是static,private或者包可見,即不加可見修飾符。
// 如在事務中,@Transactional註解不能對private,static,final,包可見的方法添加事務功能,只能爲public方法。
// 這個代理對象也須要經過代理工廠來建立,具體爲繼承了AdvisedSupport的代理工廠來建立,而不是直接建立。
@SuppressWarnings("serial")
class CglibAopProxy implements AopProxy, Serializable {
    
    ...
    
    // 建立代理對象
    public Object getProxy(@Nullable ClassLoader classLoader) {
            
            ...
            
            Class<?> rootClass = this.advised.getTargetClass();
            Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

            Class<?> proxySuperClass = rootClass;
            if (ClassUtils.isCglibProxyClass(rootClass)) {
                proxySuperClass = rootClass.getSuperclass();
                Class<?>[] additionalInterfaces = rootClass.getInterfaces();
                for (Class<?> additionalInterface : additionalInterfaces) {
                    this.advised.addInterface(additionalInterface);
                }
            }

            // Validate the class, writing log messages as necessary.
            validateClassIfNecessary(proxySuperClass, classLoader);

            // 建立目標類的子類來實現代理,即織入輔助功能
            // Configure CGLIB Enhancer...
            Enhancer enhancer = createEnhancer();
            if (classLoader != null) {
                enhancer.setClassLoader(classLoader);
                if (classLoader instanceof SmartClassLoader &&
                        ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
                    enhancer.setUseCache(false);
                }
            }
            enhancer.setSuperclass(proxySuperClass);
            enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
            enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
            enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));

            Callback[] callbacks = getCallbacks(rootClass);
            Class<?>[] types = new Class<?>[callbacks.length];
            for (int x = 0; x < types.length; x++) {
                types[x] = callbacks[x].getClass();
            }
            // fixedInterceptorMap only populated at this point, after getCallbacks call above
            enhancer.setCallbackFilter(new ProxyCallbackFilter(
                    this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
            enhancer.setCallbackTypes(types);

            // 建立代理對象
            // Generate the proxy class and create a proxy instance.
            return createProxyClassAndInstance(enhancer, callbacks);
        }
        
        ...
        
    }
    
    ...
    
}

獲取更多學習資料,能夠加羣:473984645或掃描下方二維碼ide

 

相關文章
相關標籤/搜索