浅尝Spring AOP

通过阅读本文,你首先将学习如下基础知识点:

  1. 什么是代理
  2. 什么是静态代理和动态代理
  3. 静态代理和动态代理的区别
  4. java中常见的动态代理实现以及动态代理的内在实质

在对上述概念有一定的了解之后,我们将在本地搭建一个简单的Spring项目,就可以正式开始Spring AOP的学习之旅。你将在这一部分学习到:

  1. Spring AOP使用示例
  2. 预览生成的Aop代理对象
  3. Aop代理对象的生成过程
  4. Aop代理对象的调用过程

Spring AOP的实现依赖动态代理。理解动态代理,就需要理解什么是代理

什么是代理

什么是代理?以租房为例,租房过程涉及三方,分别是客户(Client)、中介(Proxy)、房东(RealSubject),从房东(RealSubject)的视角看,他仅提供房屋出租;中介(Proxy)为房东提供了代理服务包含:联系租客、带客看房、拟定合同、签订合同、善后维护,这就是代理的好处:能为被代理对象提供额外的服务(增强)。

什么是静态代理和动态代理

静态代理

代理模式关系如图所示:

代理模式调用关系如下:

静态代理

编译前,代理Proxy类已经存在,并和目标对象Target绑定。示例代码如下:

java 复制代码
public interface Subject {
    void provideService();
}

public class RealSubject implements Subject {
    @Override
    public void provideService() {
        System.out.printf("提供服务");
    }
}

public class Proxy implements Subject {
    private Subject realSubject;

    public LandLordProxy(Subejct realSubject) {
        this.realSubject = realSubject;
    }
    
    @Override
    public void provideService() {
        System.out.printf("提供前置增强处理\n");
        this.realSubject.provideService();
        System.out.printf("提供后置增强处理\n");
    }
}
// 调用
public static void main(String[] args) {
    Subject realSubject = new RealSubject()
    Proxy proxy = new Proxy(realSubject);
    proxy.provideService();
}

动态代理

编译前,代理Proxy类是不存在的,需要借助工具编译时动态生成代理对象,并与目标对象绑定。 动态代理常见实现方式是:1. jdk动态代理;2. cglib动态代理。以下分别从使用示例、运行结果、代理类源码这三个方面进行介绍,并分析这两种动态代理的区别。

jdk动态代理

使用jdk动态代理的示例代码,如下:

java 复制代码
public interface Subject {
    void provideService();
}

public class RealSubject implements Subject {
    @Override
    public void provideService() {
        System.out.println("提供服务");
    }
}

public class DynamicProxyInvocationHandler implements InvocationHandler {
    private Subject realSubject;

    public DynamicProxyInvocationHandler(Subject realSubject) {
        this.realSubject = realSubject;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.printf("提供前置增强处理\n");
        method.invoke(realSubject, args);
        System.out.printf("提供后置增强处理\n");
        return null;
    }
}

// 调用
public static void main(String[] args) {
    // 该设置会将动态生成的代理对象保存在文件中
    System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
    Subject realSubject = new RealSubject();
    Subject dynamicProxy = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), new Class[]{Subject.class}, new DynamicProxyInvocationHandler(realSubject));
    dynamicProxy.provideService();
}

上述代码执行如下:

生成的动态代理类代码如下:

java 复制代码
public final class $Proxy0 extends Proxy implements Subject {
    private static Method m1;
    private static Method m3;
    private static Method m2;
    private static Method m0;

    public $Proxy0(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 void provideService() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    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 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"));
            m3 = Class.forName("proxy.Subject").getMethod("provideService");
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

可以看到,代理类$Proxy0实现了Subject接口,内部持有InvocationHandler对象,代理类所有方法的内部实现,实际上调的是InvacationHandler的invoke方法,最终会执行我们的增强逻辑以及被代理类的原有逻辑。

cglib动态代理

使用cglib动态代理的示例代码如下:

java 复制代码
public interface TargetInterface {
    void doSomething();
}

public class TargetClass implements TargetInterface {
    @Override
    public void doSomething() {
        System.out.println("提供服务");
    }
}

public class CglibDynamicProxy {
    public static Object getProxy(TargetInterface targetInterface) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(targetInterface.getClass());
        enhancer.setCallback((MethodInterceptor) (o, method, args, methodProxy) -> {
            System.out.println("提供前置增强处理");
            Object result = methodProxy.invokeSuper(o, args);
            System.out.println("提供后置增强处理");
            return result;
        });
        return enhancer.create();
    }
}

// 调用
public static void main(String[] args) {
    System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"/target/classes");
    TargetInterface target = new TargetClass();
    TargetInterface proxy = (TargetInterface)CglibDynamicProxy.getProxy(target);
    proxy.doSomething();
}

执行结果如下:

生成的动态代理对象代码如下:

java 复制代码
public class TargetClass$$EnhancerByCGLIB$$ece06fc1 extends TargetClass implements Factory {
    private boolean CGLIB$BOUND;
    public static Object CGLIB$FACTORY_DATA;
    private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
    private static final Callback[] CGLIB$STATIC_CALLBACKS;
    private MethodInterceptor CGLIB$CALLBACK_0;
    private static Object CGLIB$CALLBACK_FILTER;
    private static final Method CGLIB$doSomething$0$Method;
    private static final MethodProxy CGLIB$doSomething$0$Proxy;
    private static final Object[] CGLIB$emptyArgs;
    private static final Method CGLIB$equals$1$Method;
    private static final MethodProxy CGLIB$equals$1$Proxy;
    private static final Method CGLIB$toString$2$Method;
    private static final MethodProxy CGLIB$toString$2$Proxy;
    private static final Method CGLIB$hashCode$3$Method;
    private static final MethodProxy CGLIB$hashCode$3$Proxy;
    private static final Method CGLIB$clone$4$Method;
    private static final MethodProxy CGLIB$clone$4$Proxy;

    static void CGLIB$STATICHOOK1() {
        CGLIB$THREAD_CALLBACKS = new ThreadLocal();
        CGLIB$emptyArgs = new Object[0];
        Class var0 = Class.forName("proxy.cglib.TargetClass$$EnhancerByCGLIB$$ece06fc1");
        Class var1;
        Method[] var10000 = ReflectUtils.findMethods(new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());
        CGLIB$equals$1$Method = var10000[0];
        CGLIB$equals$1$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$1");
        CGLIB$toString$2$Method = var10000[1];
        CGLIB$toString$2$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$2");
        CGLIB$hashCode$3$Method = var10000[2];
        CGLIB$hashCode$3$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$3");
        CGLIB$clone$4$Method = var10000[3];
        CGLIB$clone$4$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4");
        CGLIB$doSomething$0$Method = ReflectUtils.findMethods(new String[]{"doSomething", "()V"}, (var1 = Class.forName("proxy.cglib.TargetClass")).getDeclaredMethods())[0];
        CGLIB$doSomething$0$Proxy = MethodProxy.create(var1, var0, "()V", "doSomething", "CGLIB$doSomething$0");
    }

    final void CGLIB$doSomething$0() {
        super.doSomething();
    }

    public final void doSomething() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            var10000.intercept(this, CGLIB$doSomething$0$Method, CGLIB$emptyArgs, CGLIB$doSomething$0$Proxy);
        } else {
            super.doSomething();
        }
    }

    final boolean CGLIB$equals$1(Object var1) {
        return super.equals(var1);
    }

    public final boolean equals(Object var1) {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            Object var2 = var10000.intercept(this, CGLIB$equals$1$Method, new Object[]{var1}, CGLIB$equals$1$Proxy);
            return var2 == null ? false : (Boolean)var2;
        } else {
            return super.equals(var1);
        }
    }

    final String CGLIB$toString$2() {
        return super.toString();
    }

    public final String toString() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        return var10000 != null ? (String)var10000.intercept(this, CGLIB$toString$2$Method, CGLIB$emptyArgs, CGLIB$toString$2$Proxy) : super.toString();
    }

    final int CGLIB$hashCode$3() {
        return super.hashCode();
    }

    public final int hashCode() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            Object var1 = var10000.intercept(this, CGLIB$hashCode$3$Method, CGLIB$emptyArgs, CGLIB$hashCode$3$Proxy);
            return var1 == null ? 0 : ((Number)var1).intValue();
        } else {
            return super.hashCode();
        }
    }

    final Object CGLIB$clone$4() throws CloneNotSupportedException {
        return super.clone();
    }

    protected final Object clone() throws CloneNotSupportedException {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        return var10000 != null ? var10000.intercept(this, CGLIB$clone$4$Method, CGLIB$emptyArgs, CGLIB$clone$4$Proxy) : super.clone();
    }

    public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
        String var10000 = var0.toString();
        switch (var10000.hashCode()) {
            case -508378822:
                if (var10000.equals("clone()Ljava/lang/Object;")) {
                    return CGLIB$clone$4$Proxy;
                }
                break;
            case 1826985398:
                if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
                    return CGLIB$equals$1$Proxy;
                }
                break;
            case 1913648695:
                if (var10000.equals("toString()Ljava/lang/String;")) {
                    return CGLIB$toString$2$Proxy;
                }
                break;
            case 1984935277:
                if (var10000.equals("hashCode()I")) {
                    return CGLIB$hashCode$3$Proxy;
                }
                break;
            case 2121560294:
                if (var10000.equals("doSomething()V")) {
                    return CGLIB$doSomething$0$Proxy;
                }
        }

        return null;
    }

    public TargetClass$$EnhancerByCGLIB$$ece06fc1() {
        CGLIB$BIND_CALLBACKS(this);
    }

    public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {
        CGLIB$THREAD_CALLBACKS.set(var0);
    }

    public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {
        CGLIB$STATIC_CALLBACKS = var0;
    }

    private static final void CGLIB$BIND_CALLBACKS(Object var0) {
        TargetClass$$EnhancerByCGLIB$$ece06fc1 var1 = (TargetClass$$EnhancerByCGLIB$$ece06fc1)var0;
        if (!var1.CGLIB$BOUND) {
            var1.CGLIB$BOUND = true;
            Object var10000 = CGLIB$THREAD_CALLBACKS.get();
            if (var10000 == null) {
                var10000 = CGLIB$STATIC_CALLBACKS;
                if (var10000 == null) {
                    return;
                }
            }

            var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
        }

    }

    public Object newInstance(Callback[] var1) {
        CGLIB$SET_THREAD_CALLBACKS(var1);
        TargetClass$$EnhancerByCGLIB$$ece06fc1 var10000 = new TargetClass$$EnhancerByCGLIB$$ece06fc1();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }

    public Object newInstance(Callback var1) {
        CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
        TargetClass$$EnhancerByCGLIB$$ece06fc1 var10000 = new TargetClass$$EnhancerByCGLIB$$ece06fc1();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }

    public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
        CGLIB$SET_THREAD_CALLBACKS(var3);
        TargetClass$$EnhancerByCGLIB$$ece06fc1 var10000 = new TargetClass$$EnhancerByCGLIB$$ece06fc1;
        switch (var1.length) {
            case 0:
                var10000.<init>();
                CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
                return var10000;
            default:
                throw new IllegalArgumentException("Constructor not found");
        }
    }

    public Callback getCallback(int var1) {
        CGLIB$BIND_CALLBACKS(this);
        MethodInterceptor var10000;
        switch (var1) {
            case 0:
                var10000 = this.CGLIB$CALLBACK_0;
                break;
            default:
                var10000 = null;
        }

        return var10000;
    }

    public void setCallback(int var1, Callback var2) {
        switch (var1) {
            case 0:
                this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;
            default:
        }
    }

    public Callback[] getCallbacks() {
        CGLIB$BIND_CALLBACKS(this);
        return new Callback[]{this.CGLIB$CALLBACK_0};
    }

    public void setCallbacks(Callback[] var1) {
        this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0];
    }

    static {
        CGLIB$STATICHOOK1();
    }
}

可以看到生成的代理类的doSomething()方法,在调用doSomething()时,实际上就会走到MethodInterceptor的intercept()方法,最终走我们的增强逻辑

jdk动态代理和cglib动态代理的区别

  1. 生成代理类的方式不同。通过上述代理类的代码可以发现:
    1. jdk动态代理通过实现目标接口生成代理类
    2. cglib通过继承目标类生成代理类
  2. 底层机制不同
    1. jdk动态代理,通过反射机制实现生成代理类。
    2. cglib动态代理,利用ASM架构,修改目标类的字节码、并生成子类字节码的方式生成代理类。
  3. 底层机制不同,导致使用方式不同
    1. 如果想要使用JDK动态代理,那么被代理类必须实现接口,否则不能使用。
    2. 如果想要使用CGlib动态代理,那么被代理类不能使用final修饰类和方法。

参考JDK 动态代理与 CGLIB 动态代理

Spring AOP概览

我们已经了解什么动态代理,并且从上帝视角我们得知:Spring AOP的底层实现借助于动态代理技术。那么现在我们自然会想问:1. Spring AOP怎么使用?2. Spring AOP生成怎样的代理类,生成代理类的过程?3. Spring AOP怎么执行我们定义的增强逻辑?

Spring AOP的使用

为了让我们在代码层面对Spring Aop有个直观的认识,下面将列举2个简单的使用示例,分别说明切面为接口、切面类的情况。需要引入的相关依赖,已放在文章的末尾。

切面为接口

以下是切面为接口的Spring AOP使用示例:

java 复制代码
public interface MyTestInterface {
    void test();
}

@Component
public class MytTestInterfaceImpl implements MyTestInterface {
    @Override
    public void test() {
        System.out.println("这是MytTestInterfaceImpl在执行");
    }
}

@Component
@Aspect
public class MyTestClazzAop {
    @Pointcut("execution(* proxy.aop.MyTestInterface.test(..))")
    public void pt() {}

    @Before("pt()")
    public void before(JoinPoint jp) {
        System.out.println("这是前置增强");
    }

    @After("pt()")
    public void after() {
        System.out.println("这是后置增强");
    }
}

@Configuration
@EnableAspectJAutoProxy
public class TestConfig {
}

public class App {
    public static void main(String[] args) {
        // proxy.aop换成你项目中实际的package
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext("proxy.aop");
        MyTestInterface bean = applicationContext.getBean(MyTestInterface.class);
        bean.test();
    }
}

以上代码,首先定义一个接口MyTestInterface,再定义了一个实现类MytTestInterfaceImpl,MytTestInterfaceImpl实现了test接口并打印了一行日志。然后再定义了MyTestAop,MyTestAop先指定了切面,并且定义了前置和后置增强,增强逻辑就是打印了两行日志。最后,我们通过IoC容器获取MyTestInterface类型的bean,调用test()打印的日志如下:

java 复制代码
这是前置增强
这是MytTestInterfaceImpl在执行
这是后置增强

切面为类

以下是切面为类的Spring AOP使用示例:

java 复制代码
@Component
public class MyTestClazz {
    public void test() {
        System.out.println("这是MyTestClazz在执行");
    }
}

@Component
@Aspect
public class MyTestClazzAop {
    @Pointcut("execution(* proxy.aop.MyTestClazz.test(..))")
    public void pt(){}


    @Before("pt()")
    public void before(JoinPoint jp) {
        System.out.println("这是前置增强");
    }

    @After("pt()")
    public void after() {
        System.out.println("这是后置增强");
    }
}

@Configuration
@EnableAspectJAutoProxy
public class TestConfig {
}

public class App {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext("proxy.aop");
        MyTestClazz bean = applicationContext.getBean(MyTestClazz.class);
        bean.test();
    }
}

执行结果如下

java 复制代码
这是前置增强
这是MyTestClazz在执行
这是后置增强

Spring AOP代理类的生成

预览Spring AOP代理类

上述介绍了SpringAOP两种使用方式,一种切面为接口,一种切面为类。这两种使用方式对Spring来说,生成的代理类有何不同呢?要了解它们之间有差异,先对比下面三种情况applicationContext.getBean获取的类。

  1. 不使用Spring AOP,获取的是类MyTestInterfaceImpl对象,以此为基准。
  1. 切面为接口,获取的是类$Proxy{数字},由jdk动态代理生成(属性是JdkDynamicAopProxy可知)
  1. 切面为类,获取的是类MyTestClazz <math xmlns="http://www.w3.org/1998/Math/MathML"> E n h a n c e r B y S p r i n g C G L I B EnhancerBySpringCGLIB </math>EnhancerBySpringCGLIB74260093,由cglib动态代理生成(看类名可知)。

创建Spring AOP代理类的生成过程

注册AnnotationAwareAspectJAutoProxyCreator

在上面的使用实例中,开启Spring AOP需要引入注解@EnableAspectJAutoProxy,看名字猜作用,这个注解的作用大概是:开启Aspectj自动代理。这个注解的作用是将AnnotaitonAwareAspectJAutoProxyCreator注入bean容器。 注册AnnotaitonAwareAspectJAutoProxyCreator的过程如图所示

@EnableAspectJAutoProxy注解定义如下:

java 复制代码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

	/**
	 * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
	 * to standard Java interface-based proxies. The default is {@code false}.
	 */
	boolean proxyTargetClass() default false;

	/**
	 * Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
	 * for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
	 * Off by default, i.e. no guarantees that {@code AopContext} access will work.
	 * @since 4.3.1
	 */
	boolean exposeProxy() default false;

}

@Import(AspectJAutoProxyRegistrar.class)引入了AspectJAutoProxyRegistrar类,再次看类名猜作用:AspectJ自动代理注册器。AspectJAutoProxyRegistrar类定义如下:

java 复制代码
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

	/**
	 * Register, escalate, and configure the AspectJ auto proxy creator based on the value
	 * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
	 * {@code @Configuration} class.
	 */
	@Override
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

		AnnotationAttributes enableAspectJAutoProxy =
				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
		if (enableAspectJAutoProxy != null) {
			if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			}
			if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
				AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
			}
		}
	}

}

AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrar,从类名可推断AspectJAutoProxyRegistrar具备了将BeanDefinition注册到容器的能力。重点看接口的具体实现,AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry)做了注册BeanDefinition的动作。registerAspectJAnnotationAutoProxyCreatorIfNecessary的定义如下

java 复制代码
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
    BeanDefinitionRegistry registry, @Nullable Object source) {

    return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}

这里调用引入了registerOrEscalateApcAsRequired方法,将AnnotationAwareAspectJAutoProxyCreator.class作为参数传入。大胆猜测应该是将AnnotationAwareAspectJAutoProxyCreator注册到容器中。registerOrEscalateApcAsRequired方法的具体实现如下

java 复制代码
public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
			"org.springframework.aop.config.internalAutoProxyCreator";

private static BeanDefinition registerOrEscalateApcAsRequired(
			Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {

		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");

		if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
			BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
			if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
				int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
				int requiredPriority = findPriorityForClass(cls);
				if (currentPriority < requiredPriority) {
					apcDefinition.setBeanClassName(cls.getName());
				}
			}
			return null;
		}

		RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
		beanDefinition.setSource(source);
		beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
		beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
		registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
		return beanDefinition;
	}

逻辑清晰:将AnnotationAwareAspectJAutoProxyCreator.class作为注册到容器中,beanName叫做org.springframework.aop.config.internalAutoProxyCreator。看到这,我们发现@EnableAspectJAutoProxy最终将AnnotationAwareAspectJAutoProxyCreator注册到容器。AnnotationAwareAspectJAutoProxyCreator的继承结构如下

从上到下看,AnnotationAwareAspectJAutoProxyCreator实现了BeanPostProcessor,所以具备了对bean后置处理的能力,那有理由猜测:是不是在生成MyTestInterface或MyTestClazz的bean时,通过bean后置处理器将生了对应的代理类呢?接下重点关注BeanPostProcessor接口的实现。另外AnnotationAwareAspectJAutoProxyCreator继承了ProxyProcessorSupport,那ProxyProcessroSupport在这当中起到了什么作用?

后置处理器生成代理类

首先定位到AnnotationAwareAspectJAutoProxyCreator实现BeanPostProcessor接口的逻辑,BeanPostProccessor的接口定义如下

java 复制代码
public interface BeanPostProcessor {

	/**
	 * Apply this {@code BeanPostProcessor} to the given new bean instance <i>before</i> any bean
	 * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
	 * or a custom init-method). The bean will already be populated with property values.
	 * The returned bean instance may be a wrapper around the original.
	 * <p>The default implementation returns the given {@code bean} as-is.
	 * @param bean the new bean instance
	 * @param beanName the name of the bean
	 * @return the bean instance to use, either the original or a wrapped one;
	 * if {@code null}, no subsequent BeanPostProcessors will be invoked
	 * @throws org.springframework.beans.BeansException in case of errors
	 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
	 */
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	/**
	 * Apply this {@code BeanPostProcessor} to the given new bean instance <i>after</i> any bean
	 * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
	 * or a custom init-method). The bean will already be populated with property values.
	 * The returned bean instance may be a wrapper around the original.
	 * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
	 * instance and the objects created by the FactoryBean (as of Spring 2.0). The
	 * post-processor can decide whether to apply to either the FactoryBean or created
	 * objects or both through corresponding {@code bean instanceof FactoryBean} checks.
	 * <p>This callback will also be invoked after a short-circuiting triggered by a
	 * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
	 * in contrast to all other {@code BeanPostProcessor} callbacks.
	 * <p>The default implementation returns the given {@code bean} as-is.
	 * @param bean the new bean instance
	 * @param beanName the name of the bean
	 * @return the bean instance to use, either the original or a wrapped one;
	 * if {@code null}, no subsequent BeanPostProcessors will be invoked
	 * @throws org.springframework.beans.BeansException in case of errors
	 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
	 * @see org.springframework.beans.factory.FactoryBean
	 */
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

}

根据方法名,BeanPostProcessor提供了两个方法,分别是在bean初始化之前和之后执行。而AnnotationAwareAspectJAutoProxyCreator对这两个接口方法实现如下

java 复制代码
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
		Object cacheKey = getCacheKey(beanClass, beanName);

		if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
			if (this.advisedBeans.containsKey(cacheKey)) {
				return null;
			}
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
			}
		}

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

		return null;
	}

    @Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

这里虽然列出了postProcessBeforeInstantiation和postProcessAfterInitialization的实现,但实际上在debug的过程中,真正生成代理类对象的地方时postProcessAfterInitialization。postProcessBeforeInstantiation的作用暂时不提,有时间再去了解。

获取AopProxy对象

以下是获取AopProxy对象的过程:

这里重点看postProcessAfterInitialization的实现,代码最终会走到wrapIfNecessary()方法,其内部实现如下

java 复制代码
	/**
	 * 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;
	}

由于我们针对切面定义Aop,那么当切面涉及的bean执行21行代码时,specificInterceptors不为null,所以在22行处的判断成立,将执行23-27行的逻辑。主要看24行的createProxy方法,方法定义如下

java 复制代码
	/**
	 * 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);
		}

		return proxyFactory.getProxy(getProxyClassLoader());
	}

主体逻辑是,初始化一个ProxyFactory对象proxyFactory,在specificInterceptors转成advisors数组后,将advisors设置到proxyFactory属性中,调用proxyFactory.getProxy()得到代理对象,getProxy方法定义如下

java 复制代码
	/**
	 * Create a new proxy according to the settings in this factory.
	 * <p>Can be called repeatedly. Effect will vary if we've added
	 * or removed interfaces. Can add and remove interceptors.
	 * <p>Uses the given class loader (if necessary for proxy creation).
	 * @param classLoader the class loader to create the proxy with
	 * (or {@code null} for the low-level proxy facility's default)
	 * @return the proxy object
	 */
	public Object getProxy(@Nullable ClassLoader classLoader) {
		return createAopProxy().getProxy(classLoader);
	}

逻辑很简单,看createAorProxy()定义如下

java 复制代码
	/**
	 * Subclasses should call this to get a new AOP proxy. They should <b>not</b>
	 * create an AOP proxy with {@code this} as an argument.
	 */
	protected final synchronized AopProxy createAopProxy() {
		if (!this.active) {
			activate();
		}
		return getAopProxyFactory().createAopProxy(this);
	}

逻辑依然很简单,再看createAopProxy方法的实现

java 复制代码
    @Override
	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() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

上述代码很清晰,如果targetClass如果是接口,则返回JdkDynamicAopPorxy对象,否则返回ObjenesisCglibAopProxy对象。

调用该AopProxy的getProxy方法
  1. JdkDynamicAopProxy的getProxy方法
java 复制代码
    @Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
		}
		Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}

可以看到,通过调用Proxy.newProxyInstance(classLoader, proxiedInterfaces, this)生成代理对象,与我们编写的jdk动态代理示例类似。需要注意的是Proxy.newProxyInstance()的第3个参数传入的是this,说明JdkDynamicAopProxy是InvocationHandler的实现类,事实也正是如此

至于InvocationHandler的invoke方法将会在后续介绍。

  1. CglibAopProxy的getProxy()方法

Enhancer是不是很熟悉,我们在cglib动态代理示例中就用到了Enhancer。简单来说就是初始化Enhancer对象,设置Enhancer的Callback,最后调用Enhancer对象的create方法创建代理类。

java 复制代码
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);
		}
	}
java 复制代码
    protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
		enhancer.setInterceptDuringConstruction(false);
		enhancer.setCallbacks(callbacks);
		return (this.constructorArgs != null && this.constructorArgTypes != null ?
				enhancer.create(this.constructorArgTypes, this.constructorArgs) :
				enhancer.create());
	}

Spring AOP代理类的方法执行

Spring AOP代理类的方法执行,是指增强逻辑的执行,进一步来说就是执行@before@after注解标记的方法。

执行委托MethodInvocation实现类

回到动态代理章节,我们介绍了,如果是jdk动态代理生成的代理类,方法调用时实际执行的是InvocationHandler类的invoke();如果是cglib动态代理生成的代理类,方法调用实际执行的是MethodInterceptor类的interceptor()。

ReflectiveMethodInvocation

JdkDynamicAopProxy的invoke()

java 复制代码
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object oldProxy = null;
		boolean setProxyContext = false;

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

		try {
			if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
				// The target does not implement the equals(Object) method itself.
				return equals(args[0]);
			}
			else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
				// The target does not implement the hashCode() method itself.
				return hashCode();
			}
			else if (method.getDeclaringClass() == DecoratingProxy.class) {
				// There is only getDecoratedClass() declared -> dispatch to proxy config.
				return AopProxyUtils.ultimateTargetClass(this.advised);
			}
			else 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;
			}

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

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

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

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

41行代理获取得到interception chain,54-57行将拦截器链作为参数初始化ReflectiveMethodInvocation,最终执行ReflectiveMethodInvocation的proceed()。

CglibMethodInvocation

CglibAopProxy的getProxy()如下

java 复制代码
    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);
		}
	}

51行的getCallBacks()就是获取MethodInterceptor类(MethodInterceptor是CallBack接口的实现类)。getCallBacks()定义如下

java 复制代码
	private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
		// Parameters used for optimization choices...
		boolean exposeProxy = this.advised.isExposeProxy();
		boolean isFrozen = this.advised.isFrozen();
		boolean isStatic = this.advised.getTargetSource().isStatic();

		// Choose an "aop" interceptor (used for AOP calls).
		Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

		// Choose a "straight to target" interceptor. (used for calls that are
		// unadvised but can return this). May be required to expose the proxy.
		Callback targetInterceptor;
		if (exposeProxy) {
			targetInterceptor = (isStatic ?
					new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
					new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
		}
		else {
			targetInterceptor = (isStatic ?
					new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
					new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
		}

		// Choose a "direct to target" dispatcher (used for
		// unadvised calls to static targets that cannot return this).
		Callback targetDispatcher = (isStatic ?
				new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());

		Callback[] mainCallbacks = new Callback[] {
				aopInterceptor,  // for normal advice
				targetInterceptor,  // invoke target without considering advice, if optimized
				new SerializableNoOp(),  // no override for methods mapped to this
				targetDispatcher, this.advisedDispatcher,
				new EqualsInterceptor(this.advised),
				new HashCodeInterceptor(this.advised)
		};

		Callback[] callbacks;

		// If the target is a static one and the advice chain is frozen,
		// then we can make some optimizations by sending the AOP calls
		// direct to the target using the fixed chain for that method.
		if (isStatic && isFrozen) {
			Method[] methods = rootClass.getMethods();
			Callback[] fixedCallbacks = new Callback[methods.length];
			this.fixedInterceptorMap = new HashMap<>(methods.length);

			// TODO: small memory optimization here (can skip creation for methods with no advice)
			for (int x = 0; x < methods.length; x++) {
				Method method = methods[x];
				List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
				fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
						chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
				this.fixedInterceptorMap.put(method, x);
			}

			// Now copy both the callbacks from mainCallbacks
			// and fixedCallbacks into the callbacks array.
			callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
			System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
			System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
			this.fixedInterceptorOffset = mainCallbacks.length;
		}
		else {
			callbacks = mainCallbacks;
		}
		return callbacks;
	}

第8行的初始化了DynamicAdvisedInterceptor,它的继承结构如下

DynamicAdvisedInterceptor既然是MethodInterceptor的实现类,看下它的intercept()的实现

java 复制代码
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
			Object oldProxy = null;
			boolean setProxyContext = false;
			Object target = null;
			TargetSource targetSource = this.advised.getTargetSource();
			try {
				if (this.advised.exposeProxy) {
					// Make invocation available if necessary.
					oldProxy = AopContext.setCurrentProxy(proxy);
					setProxyContext = true;
				}
				// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
				target = targetSource.getTarget();
				Class<?> targetClass = (target != null ? target.getClass() : null);
				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.
					Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
					retVal = methodProxy.invoke(target, argsToUse);
				}
				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 && !targetSource.isStatic()) {
					targetSource.releaseTarget(target);
				}
				if (setProxyContext) {
					// Restore old proxy.
					AopContext.setCurrentProxy(oldProxy);
				}
			}
		}

29行代码初始化CglibMethodInvocation类,最终将代理逻辑委托给CglibMethodInvocation类的proceed()。看CglibMethodInvocation的继承关系如图:

执行MethodInterceptor链的invoke方法

代理类的方法执行最终委托给ReflectiveMethodInvation类的proceed()执行,代码如下

java 复制代码
	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);
		}
	}

代码的整体逻辑是,依次执行this.interceptorsAndDynamicMethodMatchers,通过debug我们知道这个列表实际数据如下图

重点关注AspectJAfterAdvice类对象、MethodBeforeAdviceInterceptor类对象,有两个我们很熟悉的词:before和After,问题1:这两个对象是由MyTestClazzAop内@before和@after修饰方法封装成的么? 截图中AspectJAfterAdvice是在MethodBeforeAdviceInterceptor,如果依次遍历执行,应该先打印"这是后置增强",而实际我们知道先打印的是"这是前置增强",这是如何实现的?

java 复制代码
    public Object invoke(MethodInvocation mi) throws Throwable {
		try {
			return mi.proceed();
		}
		finally {
			invokeAdviceMethod(getJoinPointMatch(), null, null);
		}
	}
java 复制代码
	public Object invoke(MethodInvocation mi) throws Throwable {
		this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
		return mi.proceed();
	}

我们看这两个类的invoke()的mi参数是谁?再结合ReflectiveMethodInvation#proceed()中的代码((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); mi就是ReflectiveMethodInvation对象。之所以先执行AspectJAfterAdvice#invoke却能后打印"这是后置增强",是因为在AspectJAfterAdvice#invoke内部先执行了mi.proceed(),这时又回到ReflectiveMethodInvation#proceed(),然后执行MethodBeforeAdviceInterceptor#invoke,先执行this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis())打印"这是前置增强",递归回到AspectJAfterAdvice#invoke执行invokeAdviceMethod(getJoinPointMatch(), null, null)打印"这是后置增强"。 最后再思考一下"这是MytTestInterfaceImpl在执行"是在哪里执行呢?在ReflectiveMethodInvation#proceed()的return invokeJoinpoint();

相关推荐
Chrikk1 小时前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*1 小时前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go
canyuemanyue1 小时前
go语言连续监控事件并回调处理
开发语言·后端·golang
杜杜的man1 小时前
【go从零单排】go语言中的指针
开发语言·后端·golang
customer083 小时前
【开源免费】基于SpringBoot+Vue.JS周边产品销售网站(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·java-ee·开源
Yaml44 小时前
智能化健身房管理:Spring Boot与Vue的创新解决方案
前端·spring boot·后端·mysql·vue·健身房管理
小码编匠5 小时前
一款 C# 编写的神经网络计算图框架
后端·神经网络·c#
AskHarries5 小时前
Java字节码增强库ByteBuddy
java·后端