中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何進行Spring AOP 源碼分析

發布時間:2022-01-18 09:24:26 來源:億速云 閱讀:146 作者:柒染 欄目:大數據

本篇文章為大家展示了如何進行Spring 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;    }    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()方法調用。

回顧一下之前的代碼,在 AopProxy 代理對象 觸發的 ReflectiveMethodInvocation 的 proceed() 中,在取得 攔截器 interceptor 后調用了其 invoke()方法。按照 AOP 的配置規則,ReflectiveMethodInvocation 觸發的攔截器 invoke()回調,最終會根據 Advice 類型的不同,觸發 Spring 對不同的 Advice 的攔截器封裝,比如 MethodBeforeAdvice 最終會觸發 MethodBeforeAdviceInterceptor 的 invoke()回調,其它兩個以此類推,這里就不逐一分析咯。

上述內容就是如何進行Spring AOP 源碼分析,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

聂拉木县| 通河县| 社旗县| 南溪县| 秦皇岛市| 南阳市| 桂阳县| 郓城县| 宾阳县| 利川市| 彩票| 泽普县| 洪雅县| 定陶县| 闻喜县| 凌源市| 修文县| 海宁市| 若尔盖县| 兴安盟| 双峰县| 南华县| 容城县| 张家界市| 喀喇沁旗| 抚州市| 义马市| 离岛区| 滦平县| 灌南县| 桐乡市| 宜宾市| 洪雅县| 饶平县| 洛阳市| 兴宁市| 湛江市| 衢州市| 青田县| 西畴县| 双峰县|