1. 程式人生 > 其它 >Spring 5 原始碼解析- AOP原理分析

Spring 5 原始碼解析- AOP原理分析

 

          這裡以  <aop:aspectj-autoproxy /> 開啟 AOP 方式進行程式碼分析。

配置檔案(UserAOPTest-context.xml)資訊:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation
="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="user" class="org.springframework.context.support.learning.aop.UserImpl"/> <bean id="userAspect" class
="org.springframework.context.support.learning.aop.UserAspect"/> <!-- 開啟 執行期AOP 織入 --> <aop:aspectj-autoproxy proxy-target-class="false"/> </beans>
View Code

測試用例程式碼:

public class UserAOPTest {

    @Test
    void aopTestWithJDK(){
        GenericXmlApplicationContext ctx 
= new GenericXmlApplicationContext(getClass(), "UserAOPTest-context.xml"); User user = ctx.getBean(User.class); user.doTask(); } }
View Code

程式碼:User 

public interface User {

    String doTask();

}
View Code

程式碼:UserImpl

public class UserImpl implements User{

    @Override
    public String doTask() {
        System.out.println(getClass().toString() + " doTask...");
        return "return doTask";
    }
}
View Code

程式碼:UserAspect

@Aspect
public class UserAspect {

    /** Logger used by this class. Available to subclasses. */
    protected final Log logger = LogFactory.getLog(getClass());

    @Pointcut("execution(public * org.springframework.context.support.learning.aop.User.doTask(..))")
    public void pointCut(){}

    @Before("pointCut()")
    public void before(JoinPoint point) throws Throwable {
        Signature signature = point.getSignature();
        if (logger.isInfoEnabled()) {
            logger.info("before --> begin Time:" + System.currentTimeMillis());
        }
    }

    @After("pointCut()")
    public void after(JoinPoint point) throws Throwable {
        Signature signature = point.getSignature();
        if (logger.isInfoEnabled()) {
            logger.info("after --> begin Time:" + System.currentTimeMillis());
        }
    }

    @AfterReturning(pointcut="pointCut()", returning="returnValue")
    public void afterReturning(JoinPoint point, Object returnValue) throws Throwable {
        Signature signature = point.getSignature();
        if (logger.isInfoEnabled()) {
            logger.info("afterReturning --> begin Time:" + System.currentTimeMillis());
        }
    }

    @Around("pointCut()")
    public void around(ProceedingJoinPoint pjp) throws Throwable {
        Signature signature = pjp.getSignature();
        if (logger.isInfoEnabled()) {
            logger.info("around --> begin Time:" + System.currentTimeMillis());
        }
        pjp.proceed();
        if (logger.isInfoEnabled()) {
            logger.info("around --> end Time:" + System.currentTimeMillis());
        }
    }
    
    @AfterThrowing(throwing="ex", pointcut="pointCut()")
    public void afterThrowing(Throwable ex) {
        if (logger.isInfoEnabled()) {
            logger.info("目標方法中丟擲的異常:" + ex);
            logger.info("afterThrowing --> end Time:" + System.currentTimeMillis());
        }
    }

}
View Code

 

一.讀取AOP配置,並根據AOP配置進心初始化

     XmlBeanDefinitionReader#registerBeanDefinitions()
           XmlBeanDefinitionReader#createReaderContext()
                  XmlBeanDefinitionReader#getNamespaceHandlerResolver()
                        XmlBeanDefinitionReader#createDefaultNamespaceHandlerResolver()

       1.讀取XML配置檔案時,建立預設 DefaultNamespaceHandlerResolver 例項,準備解析XML配置檔案資訊。

       2. 依次迴圈解析 <beans> 節點配置資訊。當遇到  <aop:aspectj-autoproxy /> 節點時,使用META-INF/spring.handlers中配置的處理器進行處理。

                 (在 DefaultNamespaceHandlerResolver#getHandlerMappings() 中讀取META-INF/spring.handlers配置檔案。)

                 http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler

       3. 具體解析器進行處理。
           BeanDefinitionParserDelegate#parseCustomElement(Element, BeanDefinition)

    /**
     * Parse a custom element (outside of the default namespace).
     * @param ele the element to parse
     * @param containingBd the containing bean definition (if any)
     * @return the resulting bean definition
     */
    @Nullable
    public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
        String namespaceUri = getNamespaceURI(ele);
        if (namespaceUri == null) {
            return null;
        }
        NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
        if (handler == null) {
            error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
            return null;
        }
        return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
    }
View Code

      4. 解析器初始化。

           AopNamespaceHandler#init()

public class AopNamespaceHandler extends NamespaceHandlerSupport {

    /**
     * Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the
     * '{@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}'
     * and '{@code scoped-proxy}' tags.
     */
    @Override
    public void init() {
        // In 2.0 XSD as well as in 2.5+ XSDs
        registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
        registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
        registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());

        // Only in 2.0 XSD: moved to context namespace in 2.5+
        registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
    }

}
View Code

     5. 具體配置依次分析:

       ConfigBeanDefinitionParser <aop:config>   解析如下配置。現在一般使用註解,很少這麼配置了。

<aop:config>
        <aop:pointcut id="pointCut" expression="execution(public * org.springframework.context.support.learning.aop.User.doTask(..))"/>
        <aop:aspect ref="userAspect">
            <!--前置增強-->
            <aop:before method="before" pointcut-ref="pointCut"></aop:before>
            <!--後置返回增強-->
            <aop:after-returning method="afterReturning" pointcut-ref="pointCut"
                                 returning="returnValue"></aop:after-returning>
            <!--異常通知-->
            <aop:after-throwing method="afterThrowing" pointcut-ref="pointCut"
                                throwing="ex"></aop:after-throwing>
            <!--最終通知-->
            <aop:after method="after" pointcut-ref="pointCut"></aop:after>
            <!--環繞通知-->
            <aop:around method="around" pointcut-ref="pointCut"></aop:around>
        </aop:aspect>
</aop:config>
View Code

     AspectJAutoProxyBeanDefinitionParser <aop:aspectj-autoproxy/>  解析<aop:aspectj-autoproxy/>配置節點,註冊 AnnotationAwareAspectJAutoProxyCreator 的 BeanDefinition例項。該類實現了 BeanPostProcessor 介面,在建立物件( doCreateBean() )例項時,進行後置處理。

      AspectJAutoProxyBeanDefinitionParser#parse
             AopNamespaceUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary()
                     AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry, Object)
                          registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source)

 

     ScopedProxyBeanDefinitionDecorator <aop:scoped-proxy/>    現在很少使用。
     SpringConfiguredBeanDefinitionParser <aop:spring-configured/>  現在很少使用。

 

二. AOP建立AnnotationAwareAspectJAutoProxyCreator 例項

   PostProcessorRegistrationDelegate#registerBeanPostProcessors(ConfigurableListableBeanFactory, AbstractApplicationContext)

        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);

    迴圈註冊 BeanPostProcessors  時,建立 AnnotationAwareAspectJAutoProxyCreator 例項,並新增到  BeanPostProcessor 列表。

  

    AnnotationAwareAspectJAutoProxyCreator  例項初始化時,初始化,建立後期使用的輔助物件例項。

    AnnotationAwareAspectJAutoProxyCreator#initBeanFactory()  

this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);
if (this.aspectJAdvisorFactory == null) {
    this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
}
this.aspectJAdvisorsBuilder =
        new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
View Code

  

三. 建立業務類例項,並根據切點配置建立代理物件

(一) 建立切面通知(Advice)例項 Advisor。

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(String, RootBeanDefinition, Object[])
     org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation()
           org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation()
                org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessBeforeInstantiation()
                      org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator#shouldSkip()
                           org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors()
                                org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors()

  在建立物件例項之前,解析當前程式 @Aspect 標記的類資訊 {Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class}。

   1. 獲得當前 beanFactory 中配置的所有 beanNames 資訊。

           BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false)

   2.  迴圈遍歷處理 bean 配置。

         a. 獲得  beanName 對應的型別。

         b. 判斷 beanType 是否是  isAspect(beanType)。

         c. 獲取 beanName 對應的所有通知 ( Advice ) 包裝列表 List<Advisor>。

 

org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory#getAdvisors()
     org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory#getAdvisorMethods()

     1.  獲取  aspectClass 所有方法(Method),並按 Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class 進行排序。

     org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory#getAdvisor(Method, MetadataAwareAspectInstanceFactory , int , String)

    @Override
    @Nullable
    public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
            int declarationOrderInAspect, String aspectName) {

        validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());

        AspectJExpressionPointcut expressionPointcut = getPointcut(
                candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
        if (expressionPointcut == null) {
            return null;
        }

        return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
                this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
    }
View Code

     1.建立方法切點資訊例項。AspectJExpressionPointcut

     2. 建立通知和切點關聯物件例項。 InstantiationModelAwarePointcutAdvisorImpl

     3. 最終儲存在 org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder#advisorsCache 例項中。

       InstantiationModelAwarePointcutAdvisorImpl#instantiateAdvice()

                 ReflectiveAspectJAdvisorFactory#getAdvice()

   (二). 建立bean 代理物件

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean(String, RootBeanDefinition ,Object[] )
       org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance(String, RootBeanDefinition, Object[])
       org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean(String, RootBeanDefinition, BeanWrapper)
      org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(String, Object, RootBeanDefinition)
            org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization(Object, String)
                  org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization(@Nullable, String)
                        org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary(Object bean, String beanName, Object cacheKey)

      1. 檢查是否是 AOP 相關的配置或工具類。 

      2. 檢查是否 滿足AOP代理條件。

      3. 獲取滿足條件的通知(advice)。 目標類中,只要有一個方法滿足 切入點(Pointcut)條件,就將通知(advice)新增到代理類攔截器中。

      4. 建立AOP代理例項。

    /**
     * Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
     * @param bean the raw bean instance
     * @param beanName the name of the bean
     * @param cacheKey the cache key for metadata access
     * @return a proxy wrapping the bean, or the raw bean instance as-is
     */
    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        }
        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        }
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }

        // Create proxy if we have advice.
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            Object proxy = createProxy(
                    bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }

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

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy(Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource)
     org.springframework.aop.framework.ProxyProcessorSupport#evaluateProxyInterfaces(Class<?>, ProxyFactory)
     org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#buildAdvisors(String beanName, Object[] specificInterceptors)
     org.springframework.aop.framework.ProxyFactory#getProxy(java.lang.ClassLoader)

     1. 遍歷目標類所有介面。

     2. 處理滿足條件的通知和公共通知。

     3. 通過代理工廠類,建立代理類。

    /**
     * Create an AOP proxy for the given bean.
     * @param beanClass the class of the bean
     * @param beanName the name of the bean
     * @param specificInterceptors the set of interceptors that is
     * specific to this bean (may be empty, but not null)
     * @param targetSource the TargetSource for the proxy,
     * already pre-configured to access the bean
     * @return the AOP proxy for the bean
     * @see #buildAdvisors
     */
    protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
            @Nullable Object[] specificInterceptors, TargetSource targetSource) {

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

        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.copyFrom(this);

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

        Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
        proxyFactory.addAdvisors(advisors);
        proxyFactory.setTargetSource(targetSource);
        customizeProxyFactory(proxyFactory);

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

        // Use original ClassLoader if bean class not locally loaded in overriding class loader
        ClassLoader classLoader = getProxyClassLoader();
        if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
            classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
        }
        return proxyFactory.getProxy(classLoader);
    }
View Code

 

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy(Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource)
     org.springframework.aop.framework.ProxyFactory#getProxy(java.lang.ClassLoader)
          org.springframework.aop.framework.ProxyCreatorSupport#createAopProxy()
                org.springframework.aop.framework.DefaultAopProxyFactory#createAopProxy()
          org.springframework.aop.framework.AopProxy#getProxy(java.lang.ClassLoader)

      1. 建立 AopProxy 代理例項。這裡區分 JDK動態代理(JdkDynamicAopProxy) 和 Cglib 代理(ObjenesisCglibAopProxy)。

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

      2. 使用 AopProxy 代理建立最終的代理類。區別兩種代理情況。

 

AopProxy 建立代理類例項:

    JDK 生成動態代理簡單,直接呼叫JDK的方法生成。org.springframework.aop.framework.JdkDynamicAopProxy#getProxy(java.lang.ClassLoader)

    @Override
    public Object getProxy(@Nullable ClassLoader classLoader) {
        if (logger.isTraceEnabled()) {
            logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
        }
        return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
    }
View Code

   JdkDynamic 生成的代理類:

package com.sun.proxy;


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import org.springframework.context.support.learning.aop.User;

public final class $Proxy35 extends Proxy implements User {
    private static Method m1;
    private static Method m2;
    private static Method m3;
    private static Method m0;

    public $Proxy35(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final String doTask() throws  {
        try {
            return (String)super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m3 = Class.forName("org.springframework.context.support.learning.aop.User").getMethod("doTask");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}
View Code

   

Cglib生成代理類,使用ASM位元組碼,稍微複雜些。  org.springframework.aop.framework.CglibAopProxy#getProxy(java.lang.ClassLoader)

    @Override
    public Object getProxy(@Nullable ClassLoader classLoader) {
        if (logger.isTraceEnabled()) {
            logger.trace("Creating CGLIB proxy: " + 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 (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
                proxySuperClass = rootClass.getSuperclass();
                Class<?>[] additionalInterfaces = rootClass.getInterfaces();
                for (Class<?> additionalInterface : additionalInterfaces) {
                    this.advised.addInterface(additionalInterface);
                }
            }

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

            // Configure CGLIB Enhancer...
            Enhancer enhancer = createEnhancer();
            if (classLoader != null) {
                enhancer.setClassLoader(classLoader);
                if (classLoader instanceof SmartClassLoader &&
                        ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
                    enhancer.setUseCache(false);
                }
            }
            enhancer.setSuperclass(proxySuperClass);
            enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
            enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
            enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));

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

            // Generate the proxy class and create a proxy instance.
            return createProxyClassAndInstance(enhancer, callbacks);
        }
        catch (CodeGenerationException | IllegalArgumentException ex) {
            throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
                    ": Common causes of this problem include using a final class or a non-visible class",
                    ex);
        }
        catch (Throwable ex) {
            // TargetSource.getTarget() failed
            throw new AopConfigException("Unexpected AOP exception", ex);
        }
    }
View Code

    Cglib 生成的代理類太複雜,這裡就不展示。

 

四. 通過代理類例項呼叫業務方法和增強通知(Advice)

 JdkDynamic代理:

org.springframework.aop.framework.JdkDynamicAopProxy#invoke(Object proxy, Method method, Object[] args)

     1. 獲得當前方法的 所有通知(Advice) /攔截器。獲取後,快取中放一份。

     2. 如果沒找到滿足條件的通知(Advice),則直接呼叫實際方法。AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse)

     3. 通過目標方法,方法引數,通知(Advice) 建立呼叫方法的 ReflectiveMethodInvocation 例項。

     4. 呼叫  ReflectiveMethodInvocation#proceed()。 這個方法會輪詢呼叫 通知(Advice) ,並最終呼叫實際的方法。

     org.springframework.aop.framework.ReflectiveMethodInvocation#proceed

    @Override
    @Nullable
    public Object proceed() throws Throwable {
        // We start with an index of -1 and increment early.
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
            return invokeJoinpoint();
        }

        Object interceptorOrInterceptionAdvice =
                this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
            // Evaluate dynamic method matcher here: static part will already have
            // been evaluated and found to match.
            InterceptorAndDynamicMethodMatcher dm =
                    (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
            Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
            if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
                return dm.interceptor.invoke(this);
            }
            else {
                // Dynamic matching failed.
                // Skip this interceptor and invoke the next in the chain.
                return proceed();
            }
        }
        else {
            // It's an interceptor, so we just invoke it: The pointcut will have
            // been evaluated statically before this object was constructed.
            return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
        }
    }
View Code

  (代理類例項)user.doTask() -> JdkDynamicAopProxy#invoke()

                                 -> ReflectiveMethodInvocation#proceed() ->  ExposeInvocationInterceptor#invoke(MethodInvocation mi)

                                                                                                         AspectJAroundAdvice#invoke(MethodInvocation mi)

                                                                                                         MethodBeforeAdviceInterceptor#invoke(MethodInvocation mi) 

                                                                                                         AspectJAfterAdvice#invoke(MethodInvocation mi)                               

                                                                                                         AfterReturningAdviceInterceptor#invoke(MethodInvocation mi)             

                                                                                                         AspectJAfterThrowingAdvice#invoke(MethodInvocation mi)

                                                                                                        AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments)

 

   Cglib代理:

   org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor#intercept

     1. 獲得當前方法的 所有通知(Advice) /攔截器。快取中放一份。

     2. 如果沒找到滿足條件的通知(Advice),則直接呼叫代理方法。org.springframework.cglib.proxy.MethodProxy#invoke(Object obj, Object[] args)

     3. 通過目標方法,方法引數,通知(Advice) 建立呼叫方法的 CglibMethodInvocation 例項。 CglibMethodInvocation 是 ReflectiveMethodInvocation 子類。

     4. 呼叫  CglibMethodInvocation#proceed()。 這個方法會輪詢呼叫 通知(Advice) ,並最終呼叫實際的方法。這個和JdkDynamic 類似 。