Spring原理(四)AOP的实现

  1. 概述

    下面是一个简单的使用ProxyFactoryBean实现AOP的例子。

<?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:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd"
        >
    <description>Spring公共配置 </description>

    <bean id = "testTarget" class = "com.sjj.aop.TestTarget"></bean>
    <bean id = "testAdvice1" class = "com.sjj.aop.TestAdvice1"></bean>
    <bean id = "testAdvice2" class = "com.sjj.aop.TestAdvice2"></bean>

    <bean id = "testPointcut" class = "org.springframework.aop.support.JdkRegexpMethodPointcut">
       <property name="pattern"  value = ".*itest"/>
    </bean>

    <bean id = "testAdvisor1" class = "org.springframework.aop.support.DefaultPointcutAdvisor">
       <property name="advice" ref="testAdvice1"/>
       <property name="pointcut" ref="testPointcut"/>
    </bean>

    <bean id = "testAdvisor2" class = "org.springframework.aop.support.DefaultPointcutAdvisor">
       <property name="advice" ref="testAdvice2"/>
       <property name="pointcut" ref="testPointcut"/>
    </bean>

    <bean id = "testAop" class = "org.springframework.aop.framework.ProxyFactoryBean" lazy-init="true">
       <!-- <property name="proxyInterfaces"  value = "com.sjj.aop.TestInterface" /> -->
       <property name="target" ref = "testTarget"/>
       <property name="interceptorNames" >
          <list>
             <value>testAdvisor1</value>
             <value>testAdvisor2</value>
          </list>
       </property>
    </bean>
</beans>
   public static void main(String[] args) {
        FileSystemXmlApplicationContext ctx = new 
        FileSystemXmlApplicationContext("D:/workspace/demo_spring_standalone/src/main/resources/applicationContext-aop-proxy.xml");
        TestTarget testTarget = (TestTarget) ctx.getBean("testAop");
        testTarget.itest();
    }
  1. 源码分析
    2.1 AOP初始化
    TestTarget testTarget = (TestTarget) ctx.getBean("testAop");
    上面这句代码看起来比较熟悉,没错,这句代码就是从spring上下文获取id=“testAop”的bean。从配置文件中看出,这是一个FactoryBean,这是spring专门设计为AOP服务的 ProxyFactoryBean,普通bean和FactoryBean的区别这里就不多说了。这里getBean方法直接会去调用getObject方法,

    这里跳过spring实例化bean的过程,直接进入到ProxyFactoryBean的方法getObject,

         public Object getObject() throws BeansException {
                initializeAdvisorChain();
                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();
                }
    private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
        //Advisor/Advice 链被初始化过的话,直接返回
        if (this.advisorChainInitialized) {
            return;
        }

        if (!ObjectUtils.isEmpty(this.interceptorNames)) {

            // Materialize interceptor chain from bean names.
            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 {
                    // If we get here, we need to add a named interceptor.
                    // We must check if it's a singleton or prototype.
                    Object advice;
                    if (this.singleton || this.beanFactory.isSingleton(name)) {
                        // Add the real Advisor/Advice to the chain.
                        //这里又看到了熟悉的方法,没错获取advice bean对象
                        advice = this.beanFactory.getBean(name);
                    }
                    else {
                        // It's a prototype Advice or Advisor: replace with a prototype.
                        // Avoid unnecessary creation of prototype bean just for advisor chain initialization.
                        advice = new PrototypePlaceholderAdvisor(name);
                    }
                    addAdvisorOnChainCreation(advice, name);
                }
            }
        }

        this.advisorChainInitialized = true;
    }
    private void addAdvisorOnChainCreation(Object next, String name) {
        // We need to convert to an Advisor if necessary so that our source reference
        // matches what we find from superclass interceptors.
        Advisor advisor = namedBeanToAdvisor(next);
        if (logger.isTraceEnabled()) {
            logger.trace("Adding advisor with name '" + name + "'");
        }
        addAdvisor(advisor);
    }

advisors的类型是linkedList,这是一个advisor链,所有的advisor都放在这个链表里面。

private List<Advisor> advisors = new LinkedList<Advisor>();
    public void addAdvisor(int pos, Advisor advisor) throws AopConfigException {
        if (advisor instanceof IntroductionAdvisor) {
            validateIntroductionAdvisor((IntroductionAdvisor) advisor);
        }
        addAdvisorInternal(pos, advisor);
    }

接下来继续看方法getObject下面的逻辑。

    private synchronized Object getSingletonInstance() {
        if (this.singletonInstance == null) {
            //获取target bean的对象
            this.targetSource = freshTargetSource();
            if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
                // Rely on AOP infrastructure to tell us what interfaces to proxy.
                Class<?> targetClass = getTargetClass();
                if (targetClass == null) {
                    throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
                }
                //递归的获取目标类的及其父类的接口信息,并添加到AdvisedSupport的一个全局的列表中去
                setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
            }
            // Initialize the shared singleton instance.
            super.setFrozen(this.freezeProxy);
            this.singletonInstance = getProxy(createAopProxy());
        }
        return this.singletonInstance;
    }
    protected final synchronized AopProxy createAopProxy() {
        if (!this.active) {
            activate();
        }
        /*这里的方法getAopProxyFactory,得到的是DefaultAopProxyFactory,ProxyFactoryBean继承了ProxyCreatorSupport,
         *在ProxyCreatorSupport的构造函数中设置了的 this.aopProxyFactory = new DefaultAopProxyFactory();
         *所以在实例化ProxyFactoryBean的时候就已经设置了这个aopProxyFactory 
         */
        return getAopProxyFactory().createAopProxy(this);
    }
        /*
         * 这里写明了spring内部创建代理对象的两种方式:
         * (1)jdk动态代理:适用于目标类实现了接口,且目标方法在接口中有定义。
         * (2)cglib动态代理,适用于目标类没有实现任何接口的情况。
         */
        public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
            Class<?> targetClass = config.getTargetClass();
            if (targetClass == null) {
                throw new AopConfigException("TargetSource cannot determine target class: " +
                        "Either an interface or a target is required for proxy creation.");
            }
            if (targetClass.isInterface()) {
                return new JdkDynamicAopProxy(config);
            }
            return new ObjenesisCglibAopProxy(config);
        }
        else {
            return new JdkDynamicAopProxy(config);
        }
    }
    protected Object getProxy(AopProxy aopProxy) {
        /*ProxyFactoryBean的getProxy方法,传入的参数是实际的proxy对象,也就是上一步创建的proxy,
         *也就是说实际调用的是具体的proxy对象的getProxy方法,
         */
        return aopProxy.getProxy(this.proxyClassLoader);
    }
    //这是jdk动态代理的方式
    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);
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }
    //这是cglib字节码增强的方式
    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);
                }
            }

            // 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 UndeclaredThrowableStrategy(UndeclaredThrowableException.class));

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

2.2 切面(Advice)方法触发

    testTarget.itest();

testTarget是spring封装后的目标类的代理对象实例,在平常的spring AOP的使用中,咋看起来好像和这里的用法不太一样,这里是直接从上下文中直接获取封装后的bean对象
testAOP,而正常的spring AOP的使用中是使用aop标签在命令行中定义aop相关的元素,或者使用aop相关的注解,而且是直接调用目标方法,只要符合定义的aop切面的拦截规
则,该方法就会被拦截,并且织入advice逻辑。我们并没有去给目标对象生产代理,看似是这样的,其实封装代理这一步spring已经帮我们做了,也就是说我们运行程序的时候实际
上调用的是spring创建的目标对象的代理对象,只是创建代理对象这一步对用户来说是透明的。

下面我们看下相关的源码:

如果熟悉jdk动态代理的话,应该知道invoke方法,是通过jdk动态代理的方式实现代理需要重写的接口InvocationHandler的方法。

        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        MethodInvocation invocation;
        Object oldProxy = null;
        boolean setProxyContext = false;

        TargetSource targetSource = this.advised.targetSource;
        Class<?> targetClass = null;
        Object target = null;

        try {
            if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
                // The target does not implement the equals(Object) method itself.
                return equals(args[0]);
            }
            if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
                // The target does not implement the hashCode() method itself.
                return hashCode();
            }
            if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                    method.getDeclaringClass().isAssignableFrom(Advised.class)) {
                // Service invocations on ProxyConfig with the proxy config...
                return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
            }

            Object retVal;

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

            // May be null. Get as late as possible to minimize the time we "own" the target,
            // in case it comes from a pool.
            target = targetSource.getTarget();
            if (target != null) {
                targetClass = target.getClass();
            }

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

            // Check whether we have any advice. If we don't, we can fallback on direct
            // reflective invocation of the target, and avoid creating a MethodInvocation.
            if (chain.isEmpty()) {
                // We can skip creating a MethodInvocation: just invoke the target directly
                // Note that the final invoker must be an InvokerInterceptor so we know it does
                // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
                retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
            }
            else {
                // We need to create a method invocation...
                invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                // Proceed to the joinpoint through the interceptor chain.
                retVal = invocation.proceed();
            }

            // Massage return value if necessary.
            Class<?> returnType = method.getReturnType();
            if (retVal != null && retVal == target && returnType.isInstance(proxy) &&
                    !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
                // Special case: it returned "this" and the return type of the method
                // is type-compatible. Note that we can't help if the target sets
                // a reference to itself in another returned object.
                retVal = proxy;
            }
            else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
                throw new AopInvocationException(
                        "Null return value from advice does not match primitive return type for: " + method);
            }
            return retVal;
        }
        finally {
            if (target != null && !targetSource.isStatic()) {
                // Must have come from TargetSource.
                targetSource.releaseTarget(target);
            }
            if (setProxyContext) {
                // Restore old proxy.
                AopContext.setCurrentProxy(oldProxy);
            }
        }
    }
    //当拦截器链为空的话,会调用方法AopUtils.invokeJoinpointUsingReflection,直接调用目标对象的目标方法
    public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args)
            throws Throwable {

        // Use reflection to invoke the method.
        try {
            ReflectionUtils.makeAccessible(method);
            return method.invoke(target, args);
        }
        catch (InvocationTargetException ex) {
            // Invoked method threw a checked exception.
            // We must rethrow it. The client won't see the interceptor.
            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);
        }
    }

熟悉cglib动态代理的应该熟悉下面这个方法,方法intercept就是cglib方式实现动态代理时需要重写接口MethodInterceptor的方法。

            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) {
                    // Make invocation available if necessary.
                    oldProxy = AopContext.setCurrentProxy(proxy);
                    setProxyContext = true;
                }
                // May be null. Get as late as possible to minimize the time we
                // "own" the target, in case it comes from a pool...
                target = getTarget();
                if (target != null) {
                    targetClass = target.getClass();
                }
                //获取所有的拦截器及advice
                List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
                Object retVal;
                // Check whether we only have one InvokerInterceptor: that is,
                // no real advice, but just reflective invocation of the target.
                if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
                    // We can skip creating a MethodInvocation: just invoke the target directly.
                    // Note that the final invoker must be an InvokerInterceptor, so we know
                    // it does nothing but a reflective operation on the target, and no hot
                    // swapping or fancy proxying.
                    retVal = methodProxy.invoke(target, args);
                }
                else {
                    // We need to create a method invocation...
                    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);
                }
            }
        }

如果你debug调试的话,代码会进入上面提到的两个方法之一(视目标类而定,如果目标类实现了接口且目标方法在接口中有定义,spring会使用jdk动态代理来实现代理,此时则会调用invoke方法;否则使用cglib来实现代理,则会调用intercept方法)。那到底为什么会调用这两个方法(或者到底什么原理才调用的这两个方法呢?),为了弄清楚这一点,这里使用ProxyGenerator来生成一个代理类对象,并把对象写到文件中,通过反编译工具查看生成的代码。

byte[] classFile = sun.misc.ProxyGenerator.generateProxyClass("$Proxy11", TestTarget.class.getInterfaces());  

这是生成的代理类的代码,可以看到把接口的方法全部重写了一遍(包括隐式继承的Object的方法toString,hashCode,equals),最重要的是itest方法,也就是代理的目标方法。

import com.sjj.aop.TestInterface;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

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

  public $Proxy11(InvocationHandler paramInvocationHandler)
    throws 
  {
    super(paramInvocationHandler);
  }

  public final boolean equals(Object paramObject)
    throws 
  {
    try
    {
      return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  public final int hashCode()
    throws 
  {
    try
    {
      return ((Integer)this.h.invoke(this, m0, null)).intValue();
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  public final void itest()
    throws 
  {
    try
    {
      /*
       * 这里调用了invoke方法,解释开始的疑问,cglib的方式应该与此类似
       */
      this.h.invoke(this, m3, null);
      return;
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  public final String toString()
    throws 
  {
    try
    {
      return (String)this.h.invoke(this, m2, null);
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  static
  {
    try
    {
      m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
      m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
      m3 = Class.forName("com.sjj.aop.TestInterface").getMethod("itest", new Class[0]);
      m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
      return;
    }
    catch (NoSuchMethodException localNoSuchMethodException)
    {
      throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
    }
    catch (ClassNotFoundException localClassNotFoundException)
    {
      throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
    }
  }
}

最终会调用到DefaultAdvisorChainFactory的getInterceptorsAndDynamicInterceptionAdvice

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

        // This is somewhat tricky... We have to process introductions first,
        // but we need to preserve order in the ultimate list.
        List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
        Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
        boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
        /*
         *这里的GlobalAdvisorAdapterRegistry使用了单例的设计模式,具体可参考其源码
         *采用饿汉模式直接创建了一个DefaultAdvisorAdapterRegistry对象,并把三种类型的拦截器注册进去
         *具体内容参考DefaultAdvisorAdapterRegistry的构造方法
         */
        AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

        for (Advisor advisor : config.getAdvisors()) {
            if (advisor instanceof PointcutAdvisor) {
                // Add it conditionally.
                PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
                if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
                    /*根据advisor关联的advice的类型,为advice创建相应的Interceptor,
                     *AfterReturningAdviceAdapter --- AfterReturningAdviceInterceptor
                     *MethodBeforeAdviceAdapter --- MethodBeforeAdviceInterceptor
                     *ThrowsAdviceAdapter --- ThrowsAdviceInterceptor
                     */
                    MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                    MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                    //根据方法的签名和advisor的拦截规则判断方法method是否需要拦截,如果需要则把advisor下的所有advice添加到拦截器列表里去
                    if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
                        if (mm.isRuntime()) {
                            // Creating a new object instance in the getInterceptors() method
                            // isn't a problem as we normally cache created chains.
                            for (MethodInterceptor interceptor : interceptors) {
                                interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                            }
                        }
                        else {
                            interceptorList.addAll(Arrays.asList(interceptors));
                        }
                    }
                }
            }
            else if (advisor instanceof IntroductionAdvisor) {
                IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
                if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
                    Interceptor[] interceptors = registry.getInterceptors(advisor);
                    interceptorList.addAll(Arrays.asList(interceptors));
                }
            }
            else {
                Interceptor[] interceptors = registry.getInterceptors(advisor);
                interceptorList.addAll(Arrays.asList(interceptors));
            }
        }

        return interceptorList;
    }
public abstract class GlobalAdvisorAdapterRegistry {

    /**
     * Keep track of a single instance so we can return it to classes that request it.
     */
    private static AdvisorAdapterRegistry instance = new DefaultAdvisorAdapterRegistry();

    /**
     * Return the singleton {@link DefaultAdvisorAdapterRegistry} instance.
     */
    public static AdvisorAdapterRegistry getInstance() {
        return instance;
    }

    /**
     * Reset the singleton {@link DefaultAdvisorAdapterRegistry}, removing any
     * {@link AdvisorAdapterRegistry#registerAdvisorAdapter(AdvisorAdapter) registered}
     * adapters.
     */
    static void reset() {
        instance = new DefaultAdvisorAdapterRegistry();
    }

}
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {

    private final List<AdvisorAdapter> adapters = new ArrayList<AdvisorAdapter>(3);


    /**
     * Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.
     */
    public DefaultAdvisorAdapterRegistry() {
        registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
        registerAdvisorAdapter(new AfterReturningAdviceAdapter());
        registerAdvisorAdapter(new ThrowsAdviceAdapter());
    }

CglibMethodInvocation是CglibAopProxy的内部类,继承了ReflectiveMethodInvocation,下面看下其proceed方法:

    public Object proceed() throws Throwable {
        //  We start with an index of -1 and increment early.
        //当遍历完整个拦截器链时,代码进入这个分支,主要功能是调用真正的目标方法
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
            return invokeJoinpoint();
        }

        /*
         * 这里interceptorsAndDynamicMethodMatchers和currentInterceptorIndex都是全局变量,
         * 这样设计的巧妙之处就在于,当具体的interceptor里的invoke方法递归调用这里proceed方法的时候,
         * 其实是对拦截器链做顺序访问,即依次调用拦截器链里的拦截器。
         */
        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;
            if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
                return dm.interceptor.invoke(this);
            }
            else {
                // Dynamic matching failed.
                // Skip this interceptor and invoke the next in the chain.
                // 如果拦截器和方法不匹配,则递归调用proceed方法,遍历拦截器链
                return proceed();
            }
        }
        else {
            // It's an interceptor, so we just invoke it: The pointcut will have
            // been evaluated statically before this object was constructed.
            /*这里的设计比较巧妙,把当前对象作为参数传进去,这样在相应的Interceptor的invoke方法里就可以递归调用
             *proceed方法,从而达到遍历拦截器链的目的
             */
            return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
        }
    }
    /*
     *这是AfterReturningAdviceInterceptor的invoke方法,注意看两者调用proceed方法、advice方法(before、afterReturning)的顺序
     */
    public Object invoke(MethodInvocation mi) throws Throwable {
        // 这里调用proceed方法,而不是目标方法,这样可以递归调用整个拦截器链的拦截器
        Object retVal = mi.proceed();
        this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
        return retVal;
    }
    /*
     *这是MethodBeforeAdviceInterceptor的invoke方法
     */
    public Object invoke(MethodInvocation mi) throws Throwable {
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
        // 这里调用proceed方法,而不是目标方法,这样可以递归调用整个拦截器链的拦截器
        return mi.proceed();
    }
        protected Object invokeJoinpoint() throws Throwable {
            if (this.publicMethod) {
                //调用真正的目标方法,在整个拦截器链最后才调用这个方法
                return this.methodProxy.invoke(this.target, this.arguments);
            }
            else {
                return super.invokeJoinpoint();
            }
        }
  1. 之前对spring一直停留在用的层面,知道springAOP是通过动态代理实现,动态代理有两种实现方式:jdk dynamic proxy和cglib字节码增强,但并不知道具体的实
    现细节,分析了AOP的实现源码之后才对如何使用者两种方式实现动态代理以及AOP的实现细节有了清晰的认识。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值