天天看點

Spring源碼(AOP):AOP源碼實作及分析,JDK動态代理的實作原了解析,Spring-Aop如何生效Spring AOP 如何生效

作者GitHub:https://github.com/AmyliaY/spring-aop-reading

AOP源碼實作及分析

1 主要的接口

1.1 Advice 通知

本接口定義了切面的增強方式,如:前置增強 BeforeAdvice,後置增強 AfterAdvice,異常增強 ThrowsAdvice 等。下面看兩個主要的子接口的源碼。

public interface MethodBeforeAdvice extends BeforeAdvice {

    /**
     * 目标方法 method 開始執行前,AOP 會回調此方法
     */
    void before(Method method, Object[] args, Object target) throws Throwable;
}

public interface AfterReturningAdvice extends AfterAdvice {

    /**
     * 目标方法 method 執行後,AOP 會回調此方法,注意,它還傳入了 method 的傳回值
     */
    void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable;
}
           

1.2 Pointcut 方法的橫切面

本接口用來定義需要增強的目标方法的集合,一般使用正規表達式去比對篩選指定範圍内的所有滿足條件的目标方法。Pointcut 接口有很多實作,我們主要看一下 JdkRegexpMethodPointcut 和 NameMatchMethodPointcut 的實作原理,前者主要通過正規表達式對方法名進行比對,後者則通過比對方法名進行比對。

// JdkRegexpMethodPointcut 的實作源碼
    private Pattern[] compiledPatterns = new Pattern[0];

    protected boolean matches(String pattern, int patternIndex) {
        Matcher matcher = this.compiledPatterns[patternIndex].matcher(pattern);
        return matcher.matches();
    }

    // NameMatchMethodPointcut 的實作源碼
    private List<String> mappedNames = new LinkedList<String>();

    public boolean matches(Method method, Class targetClass) {
        for (String mappedName : this.mappedNames) {
            if (mappedName.equals(method.getName()) || isMatch(method.getName(), mappedName)) {
                return true;
            }
        }
        return false;
    }
           

1.3 Advisor 通知器

将 Pointcut 和 Advice 有效地結合在一起。它定義了在哪些方法(Pointcut)上執行哪些動作(Advice)。下面看一下 DefaultPointcutAdvisor 的源碼實作,它通過持有 Pointcut 和 Advice 屬性來将兩者有效地結合在一起。

public class DefaultPointcutAdvisor extends AbstractGenericPointcutAdvisor implements Serializable {

    private Pointcut pointcut = Pointcut.TRUE;

    public DefaultPointcutAdvisor() {
    }

    public DefaultPointcutAdvisor(Advice advice) {
        this(Pointcut.TRUE, advice);
    }

    /**
     * 自己定義了 Pointcut屬性,而 Advice屬性 則使用父類中的定義
     */
    public DefaultPointcutAdvisor(Pointcut pointcut, Advice advice) {
        this.pointcut = pointcut;
        setAdvice(advice);
    }
}

public abstract class AbstractGenericPointcutAdvisor extends AbstractPointcutAdvisor {

    //本類是一個抽象類,其持有 Advice 的引用,而對 Pointcut 的引用,則在具體的子類中持有
    private Advice advice;

    public void setAdvice(Advice advice) {
        this.advice = advice;
    }

    public Advice getAdvice() {
        return this.advice;
    }

    @Override
    public String toString() {
        return getClass().getName() + ": advice [" + getAdvice() + "]";
    }
}
           

2 Spring AOP 的設計與實作

AOP 的實作代碼中,主要使用了 JDK 動态代理,在特定場景下(被代理對象沒有 implements 的接口)也用到了 CGLIB 生成代理對象。通過 AOP 的源碼設計可以看到,其先為目标對象建立了代理對象,這個代理對象的生成可以使用 JDK 動态代理或 CGLIB 完成。然後啟動為代理對象配置的攔截器,對橫切面(目标方法集合)進行相應的增強,将 AOP 的橫切面設計和 Proxy 模式有機地結合起來,實作了在 AOP 中定義好的各種織入方式。

2.1 ProxyFactoryBean

這裡我們主要以 ProxyFactoryBean 的實作為例,對 AOP 的實作原理進行分析。ProxyFactoryBean 主要持有目标對象 target 的代理對象 aopProxy,和 Advisor 通知器,而 Advisor 持有 Advice 和 Pointcut,這樣就可以判斷 aopProxy 中的方法 是否是某個指定的切面 Pointcut,然後根據其配置的織入方向(前置增強/後置增強),通過反射為其織入相應的增強行為 Advice。先看一下 ProxyFactoryBean 的配置和使用。

<!-- 定義自己的 Advisor 實作,其中包含了 Pointcut 和 Advice -->
<bean id="myAdvisor" class="com.shuitu.MyAdvisor"/>

<bean id="myAOP" class="org.springframework.aop.framework.ProxyFactoryBean">
	<!-- 代理類實作的接口 -->
	<property name="proxyInterface"><value>com.shuitu.ProxyInterface</value></property>
	<!-- 被代理的對象 -->
	<property name="target">
		<bean class="com.shuitu.MyTarget"/>
	</property>
	<!-- 配置相應的 Advisor -->
	<property name="interceptorNames">
		<list><value>myAdvisor</value></list>
	</property>
</bean>
           

2.2 為配置的 target 生成 AopProxy 代理對象

ProxyFactoryBean 的 getObject() 方法先對通知器鍊進行了初始化,然後根據被代理對象類型的不同,生成代理對象。

/**
     * 傳回一個代理對象,當使用者從 FactoryBean 中擷取 bean 時調用,
     * 建立此工廠要傳回的 AOP 代理的執行個體,該執行個體将作為一個單例被緩存
     */
    public Object getObject() throws BeansException {
        // 初始化通知器鍊
        initializeAdvisorChain();
        // 這裡對 Singleton 和 prototype 的類型進行區分,生成對應的 proxy
        if (isSingleton()) {
            return getSingletonInstance();
        }
        else {
            if (this.targetName == null) {
                logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
                        "Enable prototype proxies by setting the 'targetName' property.");
            }
            return newPrototypeInstance();
        }
    }
           

2.3 初始化 Advisor 鍊

/**
     * 初始化 Advisor 鍊,可以發現,其中有通過對 IoC 容器的 getBean() 方法的調用來擷取配置好的 advisor 通知器
     */
    private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
        // 如果通知器鍊已經完成初始化,則直接傳回
        if (this.advisorChainInitialized) {
            return;
        }

        if (!ObjectUtils.isEmpty(this.interceptorNames)) {
            if (this.beanFactory == null) {
                throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
                        "- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
            }

            if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&
                    this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
                throw new AopConfigException("Target required after globals");
            }

            // 這裡添加了 Advisor 鍊的調用,下面的 interceptorNames 是在配置檔案中
            // 通過 interceptorNames 進行配置的。由于每一個 Advisor 都是被配置為 bean 的,
            // 是以通過周遊 interceptorNames 得到的 name,其實就是 bean 的 id,通過這個 name(id)
            // 我們就可以從 IoC 容器中擷取對應的執行個體化 bean
            for (String name : this.interceptorNames) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Configuring advisor or advice '" + name + "'");
                }
                if (name.endsWith(GLOBAL_SUFFIX)) {
                    if (!(this.beanFactory instanceof ListableBeanFactory)) {
                        throw new AopConfigException(
                                "Can only use global advisors or interceptors with a ListableBeanFactory");
                    }
                    addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
                            name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
                }
                else {
                    // 對目前的 factoryBean 進行類型判斷,是屬于單例 bean 還是原型 bean
                    Object advice;
                    if (this.singleton || this.beanFactory.isSingleton(name)) {
                        // 通過 beanFactory 的 getBean() 方法擷取 advisor,
                        // 這個 name 是從 interceptorNames 中擷取的
                        advice = this.beanFactory.getBean(name);
                    }
                    else {
                        // 如果是原型 bean
                        advice = new PrototypePlaceholderAdvisor(name);
                    }
                    addAdvisorOnChainCreation(advice, name);
                }
            }
        }
        this.advisorChainInitialized = true;
    }
           

生成 singleton 的代理對象在 getSingletonInstance 方法中完成,這是 ProxyFactoryBean 生成 AopProxy 代理對象的調用入口。代理對象會封裝對 target 對象的調用,針對 target 對象的方法調用會被這裡生成的代理對象所攔截。

2.4 生成單例代理對象

/**
     * 傳回此類代理對象的單例執行個體,如果尚未建立該執行個體,則單例地建立它
     */
    private synchronized Object getSingletonInstance() {
        if (this.singletonInstance == null) {
            this.targetSource = freshTargetSource();
            if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
                // 根據 AOP 架構來判斷需要代理的接口
                Class targetClass = getTargetClass();
                if (targetClass == null) {
                    throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
                }
                // 設定代理對象的接口
                setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
            }
            super.setFrozen(this.freezeProxy);
            // 這裡會通過 AopProxy 來得到代理對象
            this.singletonInstance = getProxy(createAopProxy());
        }
        return this.singletonInstance;
    }

    /**
     * 通過 createAopProxy()方法 傳回的 aopProxy 擷取代理對象
     */
    protected Object getProxy(AopProxy aopProxy) {
        return aopProxy.getProxy(this.proxyClassLoader);
    }
           

上面的 createAopProxy() 方法,調用了 ProxyFactoryBean 的父類 ProxyCreatorSupport 中的實作。

public class ProxyCreatorSupport extends AdvisedSupport {

    private AopProxyFactory aopProxyFactory;

    public ProxyCreatorSupport() {
        // 注意這裡執行個體化的是一個 DefaultAopProxyFactory,是以下面的 createAopProxy() 方法
        // 中調用的也是 DefaultAopProxyFactory 的實作
        this.aopProxyFactory = new DefaultAopProxyFactory();
    }

    protected final synchronized AopProxy createAopProxy() {
        if (!this.active) {
            activate();
        }
        //調用的是 DefaultAopProxyFactory 的實作
        return getAopProxyFactory().createAopProxy(this);
    }

    public AopProxyFactory getAopProxyFactory() {
        return this.aopProxyFactory;
    }
}
           

下面看一下 AopProxyFactory 接口的實作類 DefaultAopProxyFactory 的 createAopProxy(AdvisedSupport config)方法。

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        // AopProxy 代理對象的生成過程:
        // 首先從 AdvisedSupport 對象中擷取配置的 target 目标對象的類型 targetClass,
        // 然後根據 targetClass 是否為接口采取不同的生成代理對象的政策
        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.");
            }

            /**
             * !!!!!!!!!!!!!!!!!!!!!!!!!!
             * 如果目标類是接口,則使用 JDK 動态代理,否則使用 CGLIB
             * !!!!!!!!!!!!!!!!!!!!!!!!!!
             */
            if (targetClass.isInterface()) {
                return new JdkDynamicAopProxy(config);
            }
            return CglibProxyFactory.createCglibProxy(config);
        }
        else {
            return new JdkDynamicAopProxy(config);
        }
    }
           

可以看到其根據目标對象是否實作了接口,而決定是使用 JDK 動态代理 還是 CGLIB 去生成代理對象,而 AopProxy 接口的實作類也隻有 JdkDynamicAopProxy 和 CglibAopProxy 這兩個。

2.5 JDK 動态代理 生成 AopProxy 代理對象

/**
 * 可以看到,其實作了 InvocationHandler 接口,是以肯定也定義了一個 使用 java.lang.reflect.Proxy
 * 動态生成代理對象的方法,并在實作的 invoke() 方法中為代理對象織入增強方法
 */
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {

    /** AdvisedSupport 持有一個 List<Advisor>屬性 */
    private final AdvisedSupport advised;

    public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
        Assert.notNull(config, "AdvisedSupport must not be null");
        if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
            throw new AopConfigException("No advisors and no TargetSource specified");
        }
        // 這個 advised 是一個 AdvisedSupport 對象,可以通過它擷取被代理對象 target
        // 這樣,當 invoke()方法 被 代理對象aopProxy 調用時,就可以調用 target 的目标方法了
        this.advised = config;
    }

    public Object getProxy() {
        return getProxy(ClassUtils.getDefaultClassLoader());
    }

    public Object getProxy(ClassLoader classLoader) {
        if (logger.isDebugEnabled()) {
            logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
        }

        // 擷取代理類要實作的接口
        Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
        findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);

        // 通過 java.lang.reflect.Proxy 生成代理對象并傳回
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }
}
           

通過 JdkDynamicAopProxy 的源碼可以非常清楚地看到,其使用了 JDK 動态代理 的方式生成了 代理對象。JdkDynamicAopProxy 實作了 InvocationHandler 接口,并通過 java.lang.reflect.Proxy 的 newProxyInstance()靜态方法 生成代理對象并傳回。

2.6 CGLIB 生成 AopProxy 代理對象

final class CglibAopProxy implements AopProxy, Serializable {

    /** AdvisedSupport 持有一個 List<Advisor>屬性 */
    protected final AdvisedSupport advised;

    public Object getProxy(ClassLoader classLoader) {
        if (logger.isDebugEnabled()) {
            logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
        }

        try {
            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);
                }
            }

            validateClassIfNecessary(proxySuperClass);

            // 建立并配置 Enhancer對象,Enhancer 是 CGLIB 中主要的操作類
            Enhancer enhancer = createEnhancer();
            if (classLoader != null) {
                enhancer.setClassLoader(classLoader);
                if (classLoader instanceof SmartClassLoader &&
                        ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
                    enhancer.setUseCache(false);
                }
            }
            enhancer.setSuperclass(proxySuperClass);
            enhancer.setStrategy(new MemorySafeUndeclaredThrowableStrategy(UndeclaredThrowableException.class));
            enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
            enhancer.setInterceptDuringConstruction(false);

            Callback[] callbacks = getCallbacks(rootClass);
            enhancer.setCallbacks(callbacks);
            enhancer.setCallbackFilter(new ProxyCallbackFilter(
                    this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));

            Class<?>[] types = new Class[callbacks.length];
            for (int x = 0; x < types.length; x++) {
                types[x] = callbacks[x].getClass();
            }
            enhancer.setCallbackTypes(types);

            // 通過 enhancer 生成代理對象
            Object proxy;
            if (this.constructorArgs != null) {
                proxy = enhancer.create(this.constructorArgTypes, this.constructorArgs);
            }
            else {
                proxy = enhancer.create();
            }

            return proxy;
        }
        catch (CodeGenerationException ex) {
            throw new AopConfigException("Could not generate CGLIB subclass of class [" +
                    this.advised.getTargetClass() + "]: " +
                    "Common causes of this problem include using a final class or a non-visible class",
                    ex);
        }
        catch (IllegalArgumentException ex) {
            throw new AopConfigException("Could not generate CGLIB subclass of class [" +
                    this.advised.getTargetClass() + "]: " +
                    "Common causes of this problem include using a final class or a non-visible class",
                    ex);
        }
        catch (Exception ex) {
            // TargetSource.getTarget() failed
            throw new AopConfigException("Unexpected AOP exception", ex);
        }
    }
           

為 目标對象 target 生成 代理對象 之後,在調用 代理對象 的目标方法時,目标方法會進行 invoke()回調(JDK 動态代理) 或 callbacks()回調(CGLIB),然後就可以在回調方法中對目标對象的目标方法進行攔截和增強處理了。

3 Spring AOP 攔截器調用的實作

在 Spring AOP 通過 JDK 的 Proxy 類 生成代理對象時,相關的攔截器已經配置到了代理對象持有的 InvocationHandler(即,ProxyBeanFactory) 的 invoke() 方法中,攔截器最後起作用,是通過調用代理對象的目标方法時,在代理類中觸發了 InvocationHandler 的 invoke() 回調。通過 CGLIB 實作的 AOP,原理與此相似。

3.1 JdkDynamicAopProxy 的 invoke() 攔截

前面已經通過兩種不同的方式生成了 AopProxy 代理對象,下面我們先看一下 JdkDynamicAopProxy 中的 invoke()回調方法 中對攔截器調用的實作。

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 targetSource = this.advised.targetSource;
        Class targetClass = null;
        Object target = null;

        try {
            // 如果目标對象調用的是 Obejct類 中的基本方法,如:equals()、hashCode() 則進行相應的處理
            if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
                // 如果目标對象沒有重寫 Object類 的基本方法:equals(Object other)
                return equals(args[0]);
            }
            if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
                // 如果目标對象沒有重寫 Object類 的基本方法:hashCode()
                return hashCode();
            }
            if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                    method.getDeclaringClass().isAssignableFrom(Advised.class)) {
                // 使用代理配置對 ProxyConfig 進行服務調用
                return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
            }

            Object retVal;

            if (this.advised.exposeProxy) {
                // 如果有必要,可以援引
                oldProxy = AopContext.setCurrentProxy(proxy);
                setProxyContext = true;
            }

            // 擷取目标對象,為目标方法的調用做準備
            target = targetSource.getTarget();
            if (target != null) {
                targetClass = target.getClass();
            }

            // 擷取定義好的攔截器鍊,即 Advisor清單
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

            // 如果沒有配置攔截器,就直接通過反射調用目标對象 target 的 method對象,并擷取傳回值
            if (chain.isEmpty()) {
                retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
            }
            else {
                // 如果有攔截器鍊,則需要先調用攔截器鍊中的攔截器,再調用目标的對應方法
                // 這裡通過構造 ReflectiveMethodInvocation 來實作
                invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                // 沿着攔截器鍊繼續向下處理
                retVal = invocation.proceed();
            }

            // 擷取 method 傳回值的類型
            Class<?> returnType = method.getReturnType();
            if (retVal != null && retVal == target && returnType.isInstance(proxy) &&
                    !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
                // 特殊提醒:它傳回“this”,方法的傳回類型與類型相容。
                // 注意,如果 target 在另一個傳回的對象中設定了對自身的引用,Spring 将無法處理
                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;
        }
        finally {
            if (target != null && !targetSource.isStatic()) {
                // 必須來自 TargetSource.
                targetSource.releaseTarget(target);
            }
            if (setProxyContext) {
                // 存儲舊的 proxy.
                AopContext.setCurrentProxy(oldProxy);
            }
        }
    }
}
           

3.2 CglibAopProxy 的 intercept() 攔截

CglibAopProxy 的 intercept() 回調方法實作和 JdkDynamicAopProxy 的 invoke() 非常相似,隻是在 CglibAopProxy 中構造 CglibMethodInvocation 對象來完成攔截器鍊的調用,而在 JdkDynamicAopProxy 中則是通過構造 ReflectiveMethodInvocation 對象來完成的。

final class CglibAopProxy implements AopProxy, Serializable {

    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        Object oldProxy = null;
        boolean setProxyContext = false;
        Class<?> targetClass = null;
        Object target = null;
        try {
            if (this.advised.exposeProxy) {
                oldProxy = AopContext.setCurrentProxy(proxy);
                setProxyContext = true;
            }
            target = getTarget();
            if (target != null) {
                targetClass = target.getClass();
            }
            // 從 adviced 對象中擷取配置好的攔截器鍊,advised 是一個 AdvisedSupport對象,
            // 而 AdvisedSupport 也是 ProxyFactoryBean 的父類之一。
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
            Object retVal;
            // 如果沒有配置 AOP 通知,那麼直接使用 CGLIB 的 MethodProxy 對象完成對目标方法的調用
            if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
                retVal = methodProxy.invoke(target, args);
            }
            else {
                // 通過 CglibMethodInvocation 來啟動 advice 通知,
                // CglibMethodInvocation 是 ReflectiveMethodInvocation 的子類
                // 最終還是調用的 ReflectiveMethodInvocation 對象的 proceed()方法
                retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
            }
            retVal = processReturnType(proxy, target, method, retVal);
            return retVal;
        }
        finally {
            if (target != null) {
                releaseTarget(target);
            }
            if (setProxyContext) {
                // Restore old proxy.
                AopContext.setCurrentProxy(oldProxy);
            }
        }
    }
}
           

3.3 目标對象中目标方法的調用

對目标對象中目标方法的調用,是在 AopUtils 工具類中利用反射機制完成的,具體代碼如下。

public abstract class AopUtils {

    /**
     * 使用 spring 的反射機制,調用目标方法 method 的 invoke 方法
     */
    public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args)
            throws Throwable {

        try {
            // 如果該 method 是 private的,則将其通路權限設為 public的
            ReflectionUtils.makeAccessible(method);
            // 最後利用反射完成調用
            return method.invoke(target, args);
        }
        catch (InvocationTargetException ex) {
            throw ex.getTargetException();
        }
        catch (IllegalArgumentException ex) {
            throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
                    method + "] on target [" + target + "]", ex);
        }
        catch (IllegalAccessException ex) {
            throw new AopInvocationException("Could not access method [" + method + "]", ex);
        }
    }
}
           

3.4 AOP 攔截器鍊的調用

JdkDynamicAopProxy 和 CglibAopProxy 雖然使用了不同的代理對象,但對 AOP 攔截的處理卻是相同的,都是通過 ReflectiveMethodInvocation 的 proceed() 方法實作的。

public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {

    protected final Object proxy;

    protected final Object target;

    protected final Method method;

    protected Object[] arguments;

    private final Class targetClass;

    /** MethodInterceptor和InterceptorAndDynamicMethodMatcher的集合 */
    protected final List interceptorsAndDynamicMethodMatchers;

    private int currentInterceptorIndex = -1;

    protected ReflectiveMethodInvocation(Object proxy, Object target, Method method,
            Object[] arguments, Class targetClass,
            List<Object> interceptorsAndDynamicMethodMatchers) {

        this.proxy = proxy;
        this.target = target;
        this.targetClass = targetClass;
        this.method = BridgeMethodResolver.findBridgedMethod(method);
        this.arguments = arguments;
        this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
    }

    public Object proceed() throws Throwable {
        // 從攔截器鍊中按順序依次調用攔截器,直到所有的攔截器調用完畢,開始調用目标方法,對目标方法的調用
        // 是在 invokeJoinpoint() 中通過 AopUtils 的 invokeJoinpointUsingReflection() 方法完成的
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
            // invokeJoinpoint() 直接通過 AopUtils 進行目标方法的調用
            return invokeJoinpoint();
        }

        // 這裡沿着定義好的 interceptorsAndDynamicMethodMatchers攔截器鍊 進行處理,
        // 它是一個 List,也沒有定義泛型,interceptorOrInterceptionAdvice 是其中的一個元素
        Object interceptorOrInterceptionAdvice =
                this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
            // 這裡通過攔截器的 方法比對器methodMatcher 進行方法比對,
            // 如果 目标類 的 目标方法 和配置的 Pointcut 比對,那麼這個 增強行為advice 将會被執行,
            // Pointcut 定義了切面方法(要進行增強的方法),advice 定義了增強的行為
            InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
            // 目标類的目标方法是否為 Pointcut 所定義的切面
            if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
                // 執行目前這個 攔截器interceptor 的 增強方法
                return dm.interceptor.invoke(this);
            }
            else {
                // 如果不比對,那麼 process()方法 會被遞歸調用,直到所有的攔截器都被運作過為止
                return proceed();
            }
        }
        else {
            // 如果 interceptorOrInterceptionAdvice 是一個 MethodInterceptor
            // 則直接調用其對應的方法
            return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
        }
    }
}
           

3.5 配置通知器

AdvisedSupport 中實作了擷取攔截器鍊的方法,并使用了緩存。

public class AdvisedSupport extends ProxyConfig implements Advised {

    /** TargetSource持有一個比較重要的屬性,targetClass */
    TargetSource targetSource = EMPTY_TARGET_SOURCE;

    /** 緩存 Method對象 和其對應的 攔截器鍊清單List<Advisor> */
    private transient Map<MethodCacheKey, List<Object>> methodCache;

    /** The AdvisorChainFactory to use */
    AdvisorChainFactory advisorChainFactory = new DefaultAdvisorChainFactory();

    /**
     * 擷取攔截器鍊,為提高效率,同時設定了緩存
     */
    public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class targetClass) {
        // 如果 緩存methodCache 中有就從緩存中擷取 該Method對象 對應的攔截器鍊
        // 沒有,則調用 (DefaultAdvisorChainFactory)advisorChainFactory 的
        // getInterceptorsAndDynamicInterceptionAdvice() 方法進行擷取,并緩存到 methodCache 中
        MethodCacheKey cacheKey = new MethodCacheKey(method);
        List<Object> cached = this.methodCache.get(cacheKey);
        if (cached == null) {
            // 緩存中沒有,則從 AdvisorChainFactory 中擷取,然後放進緩存
            cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
                    this, method, targetClass);
            this.methodCache.put(cacheKey, cached);
        }
        return cached;
    }
}
           

擷取攔截器鍊的工作是由 AdvisorChainFactory 完成的,他是一個攔截器鍊的生成工廠。由于 AdvisorChainFactory 接口隻有一個實作類 DefaultAdvisorChainFactory,是以我們直接看這個類中的實作就行咯。

public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {

    public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
            Advised config, Method method, Class targetClass) {

        // Advisor鍊 已經在傳進來的 config 中持有了,這裡可以直接使用。
        // Advisor 中持有 切面Pointcut 和 增強行為Advice 兩個重要屬性
        List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
        // 判斷 config 中的 Advisors 是否符合配置要求
        boolean hasIntroductions = hasMatchingIntroductions(config, targetClass);

        // 擷取注冊器,這是一個單例模式的實作
        AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
        for (Advisor advisor : config.getAdvisors()) {
            // advisor 如果是 PointcutAdvisor 的執行個體
            if (advisor instanceof PointcutAdvisor) {
                PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
                if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(targetClass)) {
                    // 攔截器鍊是通過 AdvisorAdapterRegistry 的執行個體對象 registry 來加入的,
                    // AdvisorAdapterRegistry 對 advisor 的織入起到了很大的作用
                    MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                    // 從 pointcutAdvisor 中擷取切面的方法比對器
                    MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                    // 使用 MethodMatchers 的 matches()方法 對目标類的目标方法進行比對判斷
                    if (MethodMatchers.matches(mm, method, targetClass, hasIntroductions)) {
                        if (mm.isRuntime()) {
                            for (MethodInterceptor interceptor : interceptors) {
                                interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                            }
                        }
                        else {
                            interceptorList.addAll(Arrays.asList(interceptors));
                        }
                    }
                }
            }
            // advisor 如果是 IntroductionAdvisor 的執行個體
            else if (advisor instanceof IntroductionAdvisor) {
                IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
                if (config.isPreFiltered() || ia.getClassFilter().matches(targetClass)) {
                    Interceptor[] interceptors = registry.getInterceptors(advisor);
                    interceptorList.addAll(Arrays.asList(interceptors));
                }
            }
            else {
                Interceptor[] interceptors = registry.getInterceptors(advisor);
                interceptorList.addAll(Arrays.asList(interceptors));
            }
        }
        return interceptorList;
    }

    /**
     * 判斷 config 中的 Advisors 是否符合配置要求
     */
    private static boolean hasMatchingIntroductions(Advised config, Class targetClass) {
        for (int i = 0; i < config.getAdvisors().length; i++) {
            Advisor advisor = config.getAdvisors()[i];
            if (advisor instanceof IntroductionAdvisor) {
                IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
                if (ia.getClassFilter().matches(targetClass)) {
                    return true;
                }
            }
        }
        return false;
    }
}
           

這裡的 advisor 通知器是從 AdvisedSupport 中擷取的,而 advisor 的初始化則是在 ProxyFactoryBean 的 getObject() 方法中完成的。

public class ProxyFactoryBean extends ProxyCreatorSupport
		implements FactoryBean<Object>, BeanClassLoaderAware, BeanFactoryAware {

    /**
     * 傳回一個代理對象,當使用者從 FactoryBean 中擷取 bean 時調用,
     * 建立此工廠要傳回的 AOP 代理的執行個體,該執行個體将作為一個單例被緩存
     */
    public Object getObject() throws BeansException {
        // 初始化通知器鍊
        initializeAdvisorChain();
        // 這裡對 Singleton 和 Prototype 的類型進行區分,生成對應的 proxy
        if (isSingleton()) {
            return getSingletonInstance();
        }
        else {
            if (this.targetName == null) {
                logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
                        "Enable prototype proxies by setting the 'targetName' property.");
            }
            return newPrototypeInstance();
        }
    }

    /**
     * 初始化 Advisor鍊,可以發現,其中有通過對 IoC容器 的 getBean() 方法的調用來擷取配置好的 advisor 通知器
     */
    private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
        // 如果通知器鍊已經完成初始化,則直接傳回
        if (this.advisorChainInitialized) {
            return;
        }

        if (!ObjectUtils.isEmpty(this.interceptorNames)) {
            if (this.beanFactory == null) {
                throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
                        "- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
            }

            if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&
                    this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
                throw new AopConfigException("Target required after globals");
            }

            // 這裡添加了 Advisor鍊 的調用,下面的 interceptorNames 是在配置檔案中
            // 通過 interceptorNames 進行配置的。由于每一個 Advisor 都是被配置為 bean 的,
            // 是以通過周遊 interceptorNames 得到的 name,其實就是 bean(Advisor) 的 id,通過這個 name(id)
            // 我們就可以從 IoC 容器中擷取對應的執行個體化 bean(Advisor)
            for (String name : this.interceptorNames) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Configuring advisor or advice '" + name + "'");
                }

                if (name.endsWith(GLOBAL_SUFFIX)) {
                    if (!(this.beanFactory instanceof ListableBeanFactory)) {
                        throw new AopConfigException(
                                "Can only use global advisors or interceptors with a ListableBeanFactory");
                    }
                    addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
                            name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
                }

                else {
                    // 對目前的 factoryBean 進行類型判斷,是屬于 單例bean,還是 原型bean
                    Object advice;
                    if (this.singleton || this.beanFactory.isSingleton(name)) {
                        // advisor 在檔案中配置為 bean,是以這裡通過 beanFactory 的 getBean()方法
                        // 擷取 advisor,這個 name 是從 interceptorNames 中擷取的
                        advice = this.beanFactory.getBean(name);
                    }
                    else {
                        // 如果是 原型bean
                        advice = new PrototypePlaceholderAdvisor(name);
                    }
                    // 把從 IoC容器 中擷取的 advice 放進 advisors 攔截器鍊,這個攔截器鍊是由 ProxyFactoryBean
                    // 的父類 AdvisedSupport 持有的
                    addAdvisorOnChainCreation(advice, name);
                }
            }
        }
        this.advisorChainInitialized = true;
    }
}
           

注意,Advisor 本身就被配置為 bean,是以它的擷取也是通過 IoC 容器 獲得的。

3.6 Advice 通知的實作

從 DefaultAdvisorChainFactory 類中的 getInterceptorsAndDynamicInterceptionAdvice() 方法我們可以看到,其通過 AdvisorAdapterRegistry 執行個體對象的 getInterceptors() 方法,利用配置的 advisor 完成了對攔截器的适配和注冊。

public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {

    public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
            Advised config, Method method, Class targetClass) {

        // Advisor鍊 已經在傳進來的 config 中持有了,這裡可以直接使用
        // Advisor 中持有 切面Pointcut 和 增強行為Advice 的引用
        List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
        // 判斷 config 中的 Advisors 是否符合配置要求
        boolean hasIntroductions = hasMatchingIntroductions(config, targetClass);

        // 擷取注冊器,這是一個單例模式的實作
        AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
        for (Advisor advisor : config.getAdvisors()) {
            // advisor 如果是 PointcutAdvisor 的執行個體
            if (advisor instanceof PointcutAdvisor) {
                PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
                if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(targetClass)) {
                    // 攔截器鍊是通過 AdvisorAdapterRegistry 的執行個體對象 registry 來加入的,
                    // AdvisorAdapterRegistry 對 advisor 的織入起到了很大的作用
                    MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                    // 從 pointcutAdvisor 中擷取切面的方法比對器
                    MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                    // 使用 MethodMatchers 的 matches()方法 對目标類的目标方法進行比對判斷
                    if (MethodMatchers.matches(mm, method, targetClass, hasIntroductions)) {
                        if (mm.isRuntime()) {
                            for (MethodInterceptor interceptor : interceptors) {
                                interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                            }
                        }
                        else {
                            interceptorList.addAll(Arrays.asList(interceptors));
                        }
                    }
                }
            }
            // advisor 如果是 IntroductionAdvisor 的執行個體
            else if (advisor instanceof IntroductionAdvisor) {
                IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
                if (config.isPreFiltered() || ia.getClassFilter().matches(targetClass)) {
                    Interceptor[] interceptors = registry.getInterceptors(advisor);
                    interceptorList.addAll(Arrays.asList(interceptors));
                }
            }
            else {
                Interceptor[] interceptors = registry.getInterceptors(advisor);
                interceptorList.addAll(Arrays.asList(interceptors));
            }
        }
        return interceptorList;
    }
}
           

DefaultAdvisorAdapterRegistry 的 getInterceptors()方法 封裝了 advice 織入實作的入口。

public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {

    // 持有 AdvisorAdapter 的 list,這個 list 中的 AdvisorAdapter 與
    // 實作 Spring AOP 的 advice 增強功能相對應
    private final List<AdvisorAdapter> adapters = new ArrayList<AdvisorAdapter>(3);

    /**
     * 将已實作的 AdviceAdapter 加入 list
     */
    public DefaultAdvisorAdapterRegistry() {
        registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
        registerAdvisorAdapter(new AfterReturningAdviceAdapter());
        registerAdvisorAdapter(new ThrowsAdviceAdapter());
    }

    /**
     * 如果 adviceObject 是 Advisor 的執行個體,則将 adviceObject 轉換成 Advisor 類型并傳回
     */
    public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
        if (adviceObject instanceof Advisor) {
            return (Advisor) adviceObject;
        }
        if (!(adviceObject instanceof Advice)) {
            throw new UnknownAdviceTypeException(adviceObject);
        }
        Advice advice = (Advice) adviceObject;
        if (advice instanceof MethodInterceptor) {
            return new DefaultPointcutAdvisor(advice);
        }
        for (AdvisorAdapter adapter : this.adapters) {
            if (adapter.supportsAdvice(advice)) {
                return new DefaultPointcutAdvisor(advice);
            }
        }
        throw new UnknownAdviceTypeException(advice);
    }

    public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
        List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);

        // 從 Advisor 通知器中擷取配置的 Advice
        Advice advice = advisor.getAdvice();

        // 如果 advice 是 MethodInterceptor 類型的,直接加進 interceptors,不用适配
        if (advice instanceof MethodInterceptor) {
            interceptors.add((MethodInterceptor) advice);
        }

        // 對通知進行适配,使用已經配置好的三種 AdvisorAdapter,然後從對應的
        // adapter 中取出封裝好的 AOP 編織功能的攔截器
        for (AdvisorAdapter adapter : this.adapters) {
            // adapter.supportsAdvice(advice) 方法中對 advice 的類型進行校驗
            if (adapter.supportsAdvice(advice)) {
                interceptors.add(adapter.getInterceptor(advisor));
            }
        }
        if (interceptors.isEmpty()) {
            throw new UnknownAdviceTypeException(advisor.getAdvice());
        }
        return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
    }
}
           

從 DefaultAdvisorAdapterRegistry 的實作中可以看到,其使用了一系列的 AdviceAdapter 擴充卡,如:MethodBeforeAdviceAdapter、AfterReturningAdviceAdapter、ThrowsAdviceAdapter,它們完全和 Advice 的類型一一對應,它們都是實作了 AdviceAdapter 接口的同一層次類,各自承擔着不同的适配任務,一對一地服務于不同的 Advice 實作。下面我們以 MethodBeforeAdviceAdapter 為例,看一下其源碼實作。

class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {

    public boolean supportsAdvice(Advice advice) {
        return (advice instanceof MethodBeforeAdvice);
    }

    public MethodInterceptor getInterceptor(Advisor advisor) {
        MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
        return new MethodBeforeAdviceInterceptor(advice);
    }
}
           

可以看到,其中的 getInterceptor()方法 把 Advice 從 Advisor 中取出來,然後建立了一個 MethodBeforeAdviceInterceptor 對象,并傳回,這個對象中持有對 Advice 的引用。下面我們看一下 MethodBeforeAdviceInterceptor 攔截器的源碼實作。

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {

    private MethodBeforeAdvice advice;

    /**
     * 為指定的 advice 建立對應的 MethodBeforeAdviceInterceptor 對象
     */
    public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
        Assert.notNull(advice, "Advice must not be null");
        this.advice = advice;
    }

    /**
     * 這個 invoke()方法 是攔截器的回調方法,會在代理對象的方法被調用時觸發回調
     */
    public Object invoke(MethodInvocation mi) throws Throwable {
        // 首先觸發了 advice對象 的 before()方法 的回調
        // 然後才是 MethodInvocation 的 process()方法 回調
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
        return mi.proceed();
    }
}
           

可以看到,MethodBeforeAdviceInterceptor 的 invoke()方法 先是觸發了 advice 的 before()方法,然後才是 MethodInvocation 的 proceed()方法調用。

JDK動态代理的實作原了解析

/**
 * 一般會使用實作了 InvocationHandler接口 的類作為代理對象的生産工廠,
 * 并且通過持有 被代理對象target,來在 invoke()方法 中對被代理對象的目标方法進行調用和增強,
 * 這些我們都能通過下面這段代碼看懂,但代理對象是如何生成的?invoke()方法 又是如何被調用的呢?
 */
public class ProxyFactory implements InvocationHandler {

    private Object target = null;

    public Object getInstanse(Object target){

        this.target = target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {

        Object ret = null;
        System.out.println("前置增強");
        ret = method.invoke(target, args);
        System.out.println("後置增強");
        return ret;
    }
}

/**
 * 實作了 接口MyInterface 和接口的 play()方法,可以作為被代理類
 */
public class TargetObject implements MyInterface {

    @Override
    public void play() {
        System.out.println("妲己,陪你玩 ~");
    }
}

/**
 * 測試類
 */
public class ProxyTest {

    public static void main(String[] args) {
        TargetObject target = new TargetObject();
        // ProxyFactory 實作了 InvocationHandler接口,其中的 getInstanse()方法 利用 Proxy類
        // 生成了 target目标對象 的代理對象,并傳回;且 ProxyFactory 持有對 target 的引用,可以在
        // invoke() 中完成對 target 相應方法的調用,以及目标方法前置後置的增強處理
        ProxyFactory proxyFactory = new ProxyFactory();
        // 這個 mi 就是 JDK 的 Proxy類 動态生成的代理類 $Proxy0 的執行個體,該執行個體中的方法都持有對
        // invoke()方法 的回調,是以當調用其方法時,就能夠執行 invoke() 中的增強處理
        MyInterface mi = (MyInterface) proxyFactory.getInstanse(target);
        // 這樣可以看到 mi 的 Class 到底是什麼
        System.out.println(mi.getClass());
        // 這裡實際上調用的就是 $Proxy0代理類 中對 play()方法 的實作,結合下面的代碼可以看到
        // play()方法 通過 super.h.invoke() 完成了對 InvocationHandler對象(proxyFactory)中
        // invoke()方法 的回調,是以我們才能夠通過 invoke()方法 實作對 target對象 方法的
        // 前置後置增強處理
        mi.play();
        // 總的來說,就是在 invoke()方法 中完成 target目标方法 的調用,及前置後置增強,
        // JDK 動态生成的代理類中對 invoke()方法 進行了回調
    }

    /**
     * 将 ProxyGenerator 生成的動态代理類的輸出到檔案中,利用反編譯工具 luyten 等就可
     * 以看到生成的代理類的源碼咯,下面給出了其反編譯好的代碼實作
     */
    @Test
    public void generatorSrc(){
        byte[] bytesFile = ProxyGenerator.generateProxyClass("$Proxy0", TargetObject.class.getInterfaces());
        FileOutputStream fos = null;
        try{
            String path = System.getProperty("user.dir") + "\\$Proxy0.class";
            File file = new File(path);
            fos = new FileOutputStream(file);
            fos.write(bytesFile);
            fos.flush();
        } catch (Exception e){
            e.printStackTrace();
        } finally{
            try {
                fos.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

/**
 * Proxy 生成的代理類,可以看到,其繼承了 Proxy,并且實作了 被代理類的接口MyInterface
 */
public final class $Proxy0 extends Proxy implements MyInterface {
    private static Method m1;
    private static Method m0;
    private static Method m3;
    private static Method m2;

    static {
        try {
            $Proxy0.m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            $Proxy0.m0 = Class.forName("java.lang.Object").getMethod("hashCode", (Class<?>[])new Class[0]);
            // 執行個體化 MyInterface 的 play()方法
            $Proxy0.m3 = Class.forName("com.shuitu.test.MyInterface").getMethod("play", (Class<?>[])new Class[0]);
            $Proxy0.m2 = Class.forName("java.lang.Object").getMethod("toString", (Class<?>[])new Class[0]);
        }
        catch (NoSuchMethodException ex) {
            throw new NoSuchMethodError(ex.getMessage());
        }
        catch (ClassNotFoundException ex2) {
            throw new NoClassDefFoundError(ex2.getMessage());
        }
    }

    public $Proxy0(final InvocationHandler invocationHandler) {
        super(invocationHandler);
    }

    public final void play() {
        try {
        	// 這個 h 其實就是我們調用 Proxy.newProxyInstance()方法 時傳進去的 ProxyFactory對象(它實作了
            // InvocationHandler接口),該對象的 invoke()方法 中實作了對目标對象的目标方法的增強。
        	// 看到這裡,利用動态代理實作方法增強的實作原理就全部理清咯
            super.h.invoke(this, $Proxy0.m3, null);
        }
        catch (Error | RuntimeException error) {
            throw new RuntimeException();
        }
        catch (Throwable t) {
            throw new UndeclaredThrowableException(t);
        }
    }

    public final boolean equals(final Object o) {
        try {
            return (boolean)super.h.invoke(this, $Proxy0.m1, new Object[] { o });
        }
        catch (Error | RuntimeException error) {
            throw new RuntimeException();
        }
        catch (Throwable t) {
            throw new UndeclaredThrowableException(t);
        }
    }

    public final int hashCode() {
        try {
            return (int)super.h.invoke(this, $Proxy0.m0, null);
        }
        catch (Error | RuntimeException error) {
            throw new RuntimeException();
        }
        catch (Throwable t) {
            throw new UndeclaredThrowableException(t);
        }
    }

    public final String toString() {
        try {
            return (String)super.h.invoke(this, $Proxy0.m2, null);
        }
        catch (Error | RuntimeException error) {
            throw new RuntimeException();
        }
        catch (Throwable t) {
            throw new UndeclaredThrowableException(t);
        }
    }
}
           

Spring AOP 如何生效

  • Author: HuiFer
  • 源碼閱讀倉庫: SourceHot-Spring

解析

  • 在使用 Spring AOP 技術的時候會有下面這段代碼在 xml 配置檔案中出現,來達到 Spring 支援 AOP
  • 源碼閱讀目标找到了,那麼怎麼去找入口或者對這句話的标簽解析方法呢?項目中使用搜尋
Spring源碼(AOP):AOP源碼實作及分析,JDK動态代理的實作原了解析,Spring-Aop如何生效Spring AOP 如何生效

這樣就找到了具體解析方法了

org.springframework.aop.config.AspectJAutoProxyBeanDefinitionParser

  • 類圖
    Spring源碼(AOP):AOP源碼實作及分析,JDK動态代理的實作原了解析,Spring-Aop如何生效Spring AOP 如何生效
@Override
    @Nullable
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        // 注冊 <aop:aspectj-autoproxy/>
        AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
        // 子類解析
        extendBeanDefinition(element, parserContext);
        return null;
    }

           
/**
     * 注冊 <aop:aspectj-autoproxy/>
     * @param parserContext
     * @param sourceElement
     */
    public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
            ParserContext parserContext, Element sourceElement) {

        // 注冊或者更新bean
        BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
                parserContext.getRegistry(), parserContext.extractSource(sourceElement));
        // proxy-target-class 和 expose-proxy 标簽處理
        useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
        // 注冊元件并且交給監聽器
        registerComponentIfNecessary(beanDefinition, parserContext);
    }

           
  • org.springframework.aop.config.AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)

@Nullable
    public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
            BeanDefinitionRegistry registry, @Nullable Object source) {

        // 注冊或者更新 AspectJ
        return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
    }

           
  • org.springframework.aop.config.AopConfigUtils.registerOrEscalateApcAsRequired

/**
     * 注冊或者更新 bean
     * @param cls 類
     * @param registry 注冊器
     * @param source 源類
     * @return
     */
    @Nullable
    private static BeanDefinition registerOrEscalateApcAsRequired(
            Class<?> cls, BeanDefinitionRegistry registry, @Nullable 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);
            // 建立新的bean對象
            if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
                int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
                int requiredPriority = findPriorityForClass(cls);
                if (currentPriority < requiredPriority) {
                    apcDefinition.setBeanClassName(cls.getName());
                }
            }
            // 即将建立的Bean對象和目前的注冊器相同傳回null
            return null;
        }

        RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
        beanDefinition.setSource(source);
        // 設定加載順序
        beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
        beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        // 注冊bean定義
        registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
        return beanDefinition;
    }

           

org.springframework.aop.config.AopNamespaceUtils.useClassProxyingIfNecessary

/**
     * proxy-target-class 和 expose-proxy 标簽處理
     */
    private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
        if (sourceElement != null) {
            // 處理 proxy-target-class
            boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
            if (proxyTargetClass) {
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }
            // 處理 expose-proxy
            boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
            if (exposeProxy) {
                AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
            }
        }
    }

           
  • org.springframework.aop.config.AopConfigUtils.forceAutoProxyCreatorToUseClassProxying

public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
        if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
            BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
            definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
        }
    }

           
  • forceAutoProxyCreatorToExposeProxy

    方法就不貼出代碼了,操作和

    forceAutoProxyCreatorToUseClassProxying

    一樣都是将讀取到的資料放入 bean 對象作為一個屬性存儲

總結

  • 實作

    org.springframework.beans.factory.xml.BeanDefinitionParser

    接口的類,多用于對 xml 标簽的解析,并且入口為

    parse

    方法,如果是一個 bean 對象通常會和 Spring 監聽器一起出現