Spring源码(十四)-AOP

731 阅读15分钟

日积月累,水滴石穿 😄

在小杰上篇将循环依赖的过程中,我们看了一部分关于 AOP 的代码。但是那只是 AOP 里的冰山一角。那本篇就带大家来瞧一瞧 AOP 的庐山真面目。

什么是AOP

  • Advice:单词意思是建议,不过国内程序员一般称为通知。建议切面在何时执行以及如何执行增强处理。说的直白点就是代理逻辑。通知分为如下几种:

    • Before :前置通知,在连接点前调用。

    • After :后置通知,在连接点后调用。

    • AfterReturning:返回通知,在连接点执行正常并返回后调用,执行正常也就是说在执行过程中没有发生异常。

    • AfterThrowing:异常通知,当连接点执行发生异常时调用。

    • Around:环绕通知,连接点执行之前和之后都可以执行额外代码。

  • Join point:连接点,在 Spring AOP中一个连接点就是一个方法。

  • PointCut:切点,一系列连接点的集合,可以通过表达式找到一系列的连接点。

  • Advisor:切面,也可以称为 Aspect,由 切点(pointCut)和 建议(advice)组成。

  • Target object:目标对象。

  • AOP proxy:代理对象。

  • Weaving:织入,就是将代理逻辑添加到对目标类具体连接点上,并创建代理对象的过程。

Spring AOP其实就是使用了代理模式,在 JDK动态代理Cglib动态代理的基础上继续封装了一层,根据用户的入参控制使用哪种代理。使用封装的类为 ProxyFactory

如果对于代理模式不太了解的小伙伴,可以先去看看小杰写的 设计模式-代理模式。对于在看 Spring AOP的时候有很大的帮助。

ProxyFactory的基本使用

ProxyFactory位于org.springframework.aop.framework包中。小杰带大家来演示演示效果。

  • YuanInterface
public interface YuanInterface {

	User getUserInfo(String name);
}
  • GongService
public class GongService implements YuanInterface {

	public User getUserInfo(String name) {
		System.out.println("方法执行 = " + name);
		return new User( name);
	}
}

CGLIB代理对象

public static void main(String[] args) {
    ProxyFactory proxyFactory = new ProxyFactory();

    //设置目标对象
    proxyFactory.setTarget(new GongService());

    //设置 Advice
    proxyFactory.addAdvice(new MethodBeforeAdvice() {
        @Override
        public void before(Method method, Object[] args, Object target) throws Throwable {
            System.out.println("方法之前执行");
        }
    });
    // 获得代理对象
    YuanInterface proxy = (YuanInterface)proxyFactory.getProxy();
    proxy.getUserInfo("jie");
    System.out.println(proxy.getClass().getName());
}

结果:
方法之前执行
方法执行 = jie
com.gongj.aop.GongService$$EnhancerBySpringCGLIB$$7b64455b

可以看到上述方式是由 Cglib方式产生的代理。而且我们可以发现使用 ProxyFactory之后,不需要手动再代理逻辑中在调用 method.invoke(target,args);执行目标对象的方法了,代理逻辑自动就帮我调用了。

当然我们也可再次手动调用:

//设置 Advice
proxyFactory.addAdvice(new MethodBeforeAdvice() {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("AOP代理方法之前执行");
        //手动执行目标对象的方法
        method.invoke(target,args);
    }
});

结果:
方法之前执行
方法执行 = jie
方法执行 = jie
com.gongj.aop.GongService$$EnhancerBySpringCGLIB$$7b64455b

JDK代理对象

如果要使用JDK方式产生代理,可以使用以下方式:

//设置接口
proxyFactory.setInterfaces(new Class[]{YuanInterface.class});

结果:
AOP代理方法之前执行
方法执行 = jie
com.sun.proxy.$Proxy0

那如果我设置了接口,我也想使用 Cglib代理怎么办呢?这样无理的要求也是可以满足你滴!

proxyFactory.setProxyTargetClass(true);
proxyFactory.setOptimize(true);

上述两个值任意设置一个,就可以使用 Cglib代理了。需要记住的是 proxyTargetClass,在 @EnableAspectJAutoProxy 注解可以指定该属性的值。

public static void main(String[] args) {
    ProxyFactory proxyFactory = new ProxyFactory();

    //设置目标对象
    proxyFactory.setTarget(new GongService());
    proxyFactory.setProxyTargetClass(true);
    //proxyFactory.setOptimize(true);

    //设置接口
    proxyFactory.setInterfaces(new Class[]{YuanInterface.class});
    //设置 Advice
    proxyFactory.addAdvice(new MethodBeforeAdvice() {
        @Override
        public void before(Method method, Object[] args, Object target) throws Throwable {
            System.out.println("方法之前执行");
            //手动执行目标对象的方法
            method.invoke(target,args);
        }
    });
    // 获得代理对象
    YuanInterface proxy = (YuanInterface)proxyFactory.getProxy();
    proxy.getUserInfo("jie");
    System.out.println(proxy.getClass().getName());
}

结果:
方法之前执行
方法执行 = jie
方法执行 = jie
com.gongj.aop.GongService$$EnhancerBySpringCGLIB$$4ddaaf0f

自定义 Advisor

YuanInterface 接口中增加一个方法 findById,子类GongService并进行重写。

//YuanInterface
User findById(Long id);


//GongService
@Override
public User findById(Long id) {
    System.out.println("方法执行 = " + id);
    return new User("程序员小杰");
}
  • 启动类
public static void main(String[] args) {
    ProxyFactory proxyFactory = new ProxyFactory();

    //设置目标对象
    proxyFactory.setTarget(new GongService());
    //proxyFactory.setProxyTargetClass(true);
    //proxyFactory.setTargetClass(YuanInterface.class);
    //proxyFactory.setOptimize(true);

    //设置接口
    proxyFactory.setInterfaces(new Class[]{YuanInterface.class});
    //设置 Advice
    proxyFactory.addAdvice(new MethodBeforeAdvice() {
        @Override
        public void before(Method method, Object[] args, Object target) throws Throwable {
            System.out.println("方法之前执行");
            //手动执行目标对象的方法
            method.invoke(target,args);
        }
    });
    // 获得代理对象
    YuanInterface proxy = (YuanInterface)proxyFactory.getProxy();
    proxy.getUserInfo("原来测测");
    proxy.findById(11L);
    System.out.println(proxy.getClass().getName());
}
结果:
方法之前执行
方法执行 = 原来测测
方法执行 = 原来测测
方法之前执行
方法执行 = 11
方法执行 = 11
com.sun.proxy.$Proxy0    

根据结果可知getUserInfo方法和 findById方法都被增强了,但是我现在就只想增强 getUserInfo方法怎么办。

这时,就出现了Advisor,表示一个Advice可以应用在哪些地方,而“哪些地方”就是Pointcut(切点)。

ProxyFactory中并没有提供setPointcut或者addPointcut的方法,只有addAdvisor相关的方法,而我们知道 Advisor是由 AdvicePointcut组成的。所以自定义一个 Advisor并添加到 ProxyFactory中。

import org.aopalliance.aop.Advice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.Pointcut;
import org.springframework.aop.PointcutAdvisor;
import org.springframework.aop.support.NameMatchMethodPointcut;

import java.lang.reflect.Method;

public class MyCustomizeAdvisor implements PointcutAdvisor {

	//定义 Pointcut
	@Override
	public Pointcut getPointcut() {
		//方法名称匹配器
		NameMatchMethodPointcut methodPointcut = new NameMatchMethodPointcut();
		methodPointcut.addMethodName("getUserInfo");
		return methodPointcut;
	}

	//定义 Advice
	@Override
	public Advice getAdvice() {
		MethodBeforeAdvice methodBeforeAdvice = new MethodBeforeAdvice() {
			@Override
			public void before(Method method, Object[] args, Object target) throws Throwable {
				System.out.println("方法之前执行");
				//手动执行目标对象的方法
				method.invoke(target, args);
			}
		};
		return methodBeforeAdvice;
	}

	@Override
	public boolean isPerInstance() {
		return false;
	}
}

然后将自定义的 Advisor添加到 proxyFactory中,并将之前设置的 Advice进行注释。

proxyFactory.addAdvisor(new MyCustomizeAdvisor());
		//设置 Advice
//		proxyFactory.addAdvice(new MethodBeforeAdvice() {
//			@Override
//			public void before(Method method, Object[] args, Object target) throws Throwable {
//				System.out.println("方法之前执行");
//				//手动执行目标对象的方法
//				method.invoke(target,args);
//			}
//		});

代码修改好之后,进行启动,控制台打印结果如下:

方法之前执行
方法执行 = 原来测测
方法执行 = 原来测测
方法执行 = 11
com.sun.proxy.$Proxy0

从结果可以看出来,现在只有getUserInfo方法被增强了,而 findById方法只执行了本身的逻辑。

那接下来一起来看看ProxyFactory是如何来选择使用JDK动态代理还是选择使用Cglib动态代理的!

如何选择代理对象

proxyFactory.getProxy()这段代码开始。

public Object getProxy() {
    return createAopProxy().getProxy();
}

先调用createAopProxy方法,然后再调用getProxy,我们一个一个来。

createAopProxy

该方法位于org.springframework.aop.framework.ProxyCreatorSupport类中

protected final synchronized AopProxy createAopProxy() {
    if (!this.active) {
        activate();
    }
    // 默认用的就是DefaultAopProxyFactory
    return getAopProxyFactory().createAopProxy(this);
}

获取到 DefaultAopProxyFactory然后调用createAopProxy方法。该方法有一个入参,该入参的值就是 ProxyFactory proxyFactory = new ProxyFactory();

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
  // 如果设置的targetClass是一个接口,会使用jdk动态代理
  // 默认情况下(optimize为false, isProxyTargetClass为false)
  //hasNoUserSuppliedProxyInterfaces方法,判断 ProxyFactory是否添加了接口时,也会使用jdk动态代理
  if(config.isOptimize() || config.isProxyTargetClass() ||
    hasNoUserSuppliedProxyInterfaces(config)) {
     //获得 targetClass 属性的值
    Class <?> targetClass = config.getTargetClass();
    if(targetClass == null) {
      throw new AopConfigException(
        "TargetSource cannot determine target class: " +
        "Either an interface or a target is required for proxy creation.");
    }
    //如果是接口 或者 本身就是代理类 就使用 JDK 代理
    if(targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
      return new JdkDynamicAopProxy(config);
    }
      //使用 Cglib
    return new ObjenesisCglibAopProxy(config);
  } else {
      //使用 JDK 代理
    return new JdkDynamicAopProxy(config);
  }
}

先看一下最外层 if的逻辑,config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)如果都为false,直接使用 JDK动态代理。而config.isOptimize() || config.isProxyTargetClass() 这两个的值默认都为false,当然可以手动进行设置:

proxyFactory.setOptimize(true);
proxyFactory.setProxyTargetClass(true); 

各位小伙伴是否还记得本文的第一个例子CGLIB代理对象,里面创建代理对象的方式为:CGLIB动态代理。那如果要使用CGLIB动态代理,那只能是第三个条件为 true,才有可能使用CGLIB动态代理方式创建代理对象。

private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
  //获得当前 config 里设置的接口
  Class <? > [] ifcs = config.getProxiedInterfaces();
  //如果长度为 0 或者 长度为 1 并且该接口的父类是 SpringProxy 则返回 true
  return(ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(
    ifcs[0])));
}

第一个例子中没有设置过接口,所以 ifcs的长度为 0,直接返回 true。继续往下看。

判断 targetClass是不是接口,那它的值从哪里来的呢?第一个例子中我们手动给targetClass进行赋值,

//设置目标对象
proxyFactory.setTarget(new GongService());

值来源于这呢!一起进入到 setTarget方法中。

public void setTarget(Object target) {
    setTargetSource(new SingletonTargetSource(target));
}

image-20210920233031370.png

target包装为了一个 SingletonTargetSource对象。然后传给了 setTargetSource方法。

image-20210920231754925.png

然后将 target赋予给了targetSource,然后可以发现 targetClass的值就是来源于targetSource.getTargetClass()。那这样子的话 targetClass.isInterface()的返回值为 fasle,为什么这么肯定呢,因为入口调用的是 proxyFactory.setTarget(new GongService());方法只能传入实例,setTarget没办法传入new YuanInterface()

既然有getTargetClass方法,那应该也有 setTargetClass方法。这里可以如此使用:proxyFactory.setTargetClass(YuanInterface.class);。那也看一下setTargetClass方法:

public void setTargetClass(@Nullable Class<?> targetClass) {
    this.targetSource = EmptyTargetSource.forClass(targetClass);
}

可以发现这时候构建的是EmptyTargetSource对象。那它跟 SingletonTargetSource对象有什么区别呢?

对象类型有无target值有无targetClass值
SingletonTargetSource
EmptyTargetSource

可以发现EmptyTargetSource对象是没有 target的值,target没值会发生什么呢?

public static void main(String[] args) {
    ProxyFactory proxyFactory = new ProxyFactory();

    //设置目标对象
    proxyFactory.setTarget(new GongService());
    //设置目标对象 Class
    proxyFactory.setTargetClass(YuanInterface.class);
    //设置接口
    //proxyFactory.setInterfaces(new Class[]{YuanInterface.class});

    //设置 Advice
    proxyFactory.addAdvice(new MethodBeforeAdvice() {
        @Override
        public void before(Method method, Object[] args, Object target) throws Throwable {
            System.out.println("方法之前执行");
            //手动执行目标对象的方法
            //method.invoke(target,args);
        }
    });
    // 获得代理对象
    YuanInterface proxy = (YuanInterface)proxyFactory.getProxy();
    proxy.getUserInfo("jie");
    System.out.println(proxy.getClass().getName());
}

上述这种写法肯定是使用 JDK动态代理方式产生代理对象。启动控制台打印结果如下:

image-20210921024919524.png

出现了 NullPointerException,因为目标对象是空的,执行完 before之后,就会执行method.invoke

从上述源码可以看出来,虽然 Cglib本身是支持使用接口生成代理对象,但是Sprign AOP对其进行了限制,如果是接口就只能使用 JDK动态代理

getProxy

两者之间必须做出选择,到了这一步,看来你已经做出选择了。那继续来看看吧!

JdkDynamicAopProxy

我们来看一下 JdkDynamicAopProxy,使用 JDK代理对象例子进行DEBUG

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

调用有参 getProxy 方法。

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);
  // 针对所指定的接口生成代理对象,包括用户所添加的接口以及SpringProxy、Advised、DecoratingProxy
  // 所以生成的代理对象可以强制转换成上述任意一个接口类型
  return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
  • completeProxiedInterfaces
static Class <?> [] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) {
  Class <?> [] specifiedInterfaces = advised.getProxiedInterfaces();
  // 如果ProxyFactory中没有指定接口,就查看targetClass是不是接口,如果是则添加这个接口
  if(specifiedInterfaces.length == 0) {
    // No user-specified interfaces: check whether target class is an interface.
    Class <? > targetClass = advised.getTargetClass();
    if(targetClass != null) {
      if(targetClass.isInterface()) {
        advised.setInterfaces(targetClass);
      } else if(Proxy.isProxyClass(targetClass)) {
        advised.setInterfaces(targetClass.getInterfaces());
      }
      specifiedInterfaces = advised.getProxiedInterfaces();
    }
  }
  // 除开用户添加的接口之后,Spring可能还要添加几个默认的接口SpringProxy、Advised、DecoratingProxy
  boolean addSpringProxy = !advised.isInterfaceProxied(SpringProxy.class);
  boolean addAdvised = !advised.isOpaque() && !advised.isInterfaceProxied(
    Advised.class);
  boolean addDecoratingProxy = (decoratingProxy && !advised.isInterfaceProxied(
    DecoratingProxy.class));
  int nonUserIfcCount = 0;
  if(addSpringProxy) {
    nonUserIfcCount++;
  }
  if(addAdvised) {
    nonUserIfcCount++;
  }
  if(addDecoratingProxy) {
    nonUserIfcCount++;
  }
  Class <? > [] proxiedInterfaces = new Class <? > [specifiedInterfaces.length +
    nonUserIfcCount
  ];
  System.arraycopy(specifiedInterfaces, 0, proxiedInterfaces, 0,
    specifiedInterfaces.length);
  int index = specifiedInterfaces.length;
  if(addSpringProxy) {
    proxiedInterfaces[index] = SpringProxy.class;
    index++;
  }
  if(addAdvised) {
    proxiedInterfaces[index] = Advised.class;
    index++;
  }
  if(addDecoratingProxy) {
    proxiedInterfaces[index] = DecoratingProxy.class;
  }
  return proxiedInterfaces;
}

看着代码挺多的,但其实并不需要太多关注,知道结果就可以了。

image-20210921033845700.png

再继续往下,就会看到很熟悉的一段代码Proxy.newProxyInstance(当然前提是你已经知道 JDK动态代理)。

方法第三个参数的类型是InvocationHandler,但是这里传入了 this,那就说明 JdkDynamicAopProxy实现了 InvocationHandler接口。

image-20210921034403336.png

那就肯定会重写其 invoke方法。

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)) {
      return equals(args[0]);
    } else if(!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
      return hashCode();
    } else if(method.getDeclaringClass() == DecoratingProxy.class) {
      return AopProxyUtils.ultimateTargetClass(this.advised);
    } else if(!this.advised.opaque && method.getDeclaringClass().isInterface() &&
      method.getDeclaringClass().isAssignableFrom(Advised.class)) {
      return AopUtils.invokeJoinpointUsingReflection(this.advised, method,
        args);
    }
    Object retVal;
      //如果把exposeProxy属性设置为了true,那么则把代理对象设置到一个ThreadLocal(currentProxy)中去。
    if(this.advised.exposeProxy) {
      oldProxy = AopContext.setCurrentProxy(proxy);
      setProxyContext = true;
    }
    // targetSource分为两种:SingletonTargetSource、EmptyTargetSource
    // EmptyTargetSource 没有 target 值
    target = targetSource.getTarget();
    Class <? > targetClass = (target != null ? target.getClass() : null);
    // //根据当前正在执行的方法和目标类查找匹配的Advisor链  >1
    List <Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(
      method, targetClass);
    if(chain.isEmpty()) {
      Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method,
        args);
        //如果没找到 chain,直接执行目标方法
      retVal = AopUtils.invokeJoinpointUsingReflection(target, method,
        argsToUse);
    } else {
     
      MethodInvocation invocation = new ReflectiveMethodInvocation(proxy,
        target, method, args, targetClass, chain);
     // > 2
      retVal = invocation.proceed();
    }
    
    Class <? > returnType = method.getReturnType();
    if(retVal != null && retVal == target && returnType != Object.class &&
      returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(
        method.getDeclaringClass())) {
      retVal = proxy;
    } else if(retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
      throw new AopInvocationException(
        "Null return value from advice does not match primitive return type for: " +
        method);
    }
    return retVal;
  } finally {
    if(target != null && !targetSource.isStatic()) {
      targetSource.releaseTarget(target);
    }
    if(setProxyContext) {
      AopContext.setCurrentProxy(oldProxy);
    }
  }
}

看一下标记点 >1,代码的具体逻辑这里不会太过于讲解。这里找到了 chain,也就是所配置的 MethodBeforeAdvice,不过又对此进行了包装。

image-20210921042259656.png

然后看标记点 >2,构建一个 MethodInvocation对象,然后调用其proceed,会进入到子类ReflectiveMethodInvocationproceed方法。

public Object proceed() throws Throwable {
		// We start with an index of -1 and increment early.
		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
			//执行目标方法,也就是 method.invoke(target, args)
			return invokeJoinpoint();
		}

		Object interceptorOrInterceptionAdvice =
				this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
		if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
			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 {
				return proceed();
			}
		}
		else {
			// > 3
			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
		}
	}

interceptorOrInterceptionAdvice本次实例为 MethodBeforeAdviceInterceptor,所以会执行进入标记点 >3。调用 MethodBeforeAdviceInterceptor类的 invoke方法。

public Object invoke(MethodInvocation mi) throws Throwable {
    //这里就会调用所配置的 before 方法
    this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
    //这里有个递归的思想 继续调用 proceed 方法
    //如果满足最开始的那个判断条件,则执行目标方法,否则继续执行其他的代理逻辑  
    return mi.proceed();
}

CglibAopProxy

再来看一下 JdkDynamicAopProxy,使用 Cglib代理对象例子进行DEBUG

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;
    //判断当前类是否已经是通过 Cglib 生成的
    if(rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
      //如果是,则获取其父类
      proxySuperClass = rootClass.getSuperclass();
      //获得代理类实现的接口,并设置到 advised 中
      Class <? > [] additionalInterfaces = rootClass.getInterfaces();
      for(Class <? > additionalInterface: additionalInterfaces) {
        this.advised.addInterface(additionalInterface);
      }
    }
    // Validate the class, writing log messages as necessary.
    // 对 proxySuperClass 进行检查
    //1、目标方法不能是 static 、private修饰
    //2、目标方法不能是被 final 修饰
    //3、目标方法的访问权限需要为 public、protected级别,不能是包访问权限
    //如果上述三个条件满足了任何一个 ,则跳过当前方法,代表当前方法不能被代理
    validateClassIfNecessary(proxySuperClass, classLoader);
    // Configure CGLIB Enhancer...
    //配置 enhancer 对象中的属性
    Enhancer enhancer = createEnhancer();
    if(classLoader != null) {
      enhancer.setClassLoader(classLoader);
      if(classLoader instanceof SmartClassLoader && ((SmartClassLoader) classLoader)
        .isClassReloadable(proxySuperClass)) {
        enhancer.setUseCache(false);
      }
    }
    enhancer.setSuperclass(proxySuperClass);
    //这个跟 JDK 代理的逻辑是一致的
    //不过 Cglib 不会将 DecoratingProxy 接口添加进去
    enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
    enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
    enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
    //获取需要被执行的代理逻辑 获取到的有 7 个,不过我们只需要关心一个就可以了DynamicAdvisedInterceptor
    Callback[] callbacks = getCallbacks(rootClass);
    Class <? > [] types = new Class <? > [callbacks.length];
    for(int x = 0; x < types.length; x++) {
      types[x] = callbacks[x].getClass();
    }
    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);
  }
}

Cglib动态代理还是通过Enhancer来实现,然后设置superClassinterfacesCallbacks的值,最后通过Enhancer创建一个代理对象。对于 superClassinterfaces值的来源不再阐述。这里关注一下Callbacks的值,直接 DEBUG 在此处,看看该方法的返回值。

image-20210922233838665.png

getCallbacks方法的具体实现有兴趣的小伙伴可以自己去研究研究哈!上面返回的七个类中,我们只需要关注 DynamicAdvisedInterceptor这个,我们自定义的代理逻辑是被这个类处理的。

DynamicAdvisedInterceptor

这个类就是CglibAopProxy 的静态内部类,并且实现了MethodInterceptor接口,重写其 intercept方法。

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 {
    //如果需要暴露代理对象,则将当前代理对象设置到  currentProxy 的 ThreadLocal 中
    if(this.advised.exposeProxy) {
      oldProxy = AopContext.setCurrentProxy(proxy);
      setProxyContext = true;
    }
   
    //获得目标对象
    target = targetSource.getTarget();
    Class <?> targetClass = (target != null ? target.getClass() : null);
    //根据当前正在执行的方法和目标类查找匹配的Advisor链
    List <Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(
      method, targetClass);
    Object retVal;
    if(chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
      //对参数进行处理
      Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method,
        args);
      //没有切面逻辑,直接调用目标方法
      retVal = methodProxy.invoke(target, argsToUse);
    } else {
      // proxy: 产生的代理对象
      // target: 被代理的目标对象
      // method: 当前正在执行的目标类中的方法对象
      // args: 当前正在执行的方法参数
      // targetClass: 被代理的类
      // chain: 和当前被代理的类和正在执行的方法匹配的所有的advisor
      // methodProxy:当前正在执行的代理类中的方法对象
      //构建 CglibMethodInvocation 对象并调用 proceed 方法
      retVal = new CglibMethodInvocation(proxy, target, method, args,
        targetClass, chain, methodProxy).proceed();
    }
    //对返回值进行处理
    // 1、如果 retVal 是当前目标对象,则将代理对象进行返回
    // 2、如果 retVal 为空 并且返回值类型是非 void 的基本数据类型,则抛出异常
    retVal = processReturnType(proxy, target, method, retVal);
    return retVal;
  } finally {
    if(target != null && !targetSource.isStatic()) {
      //释放目标对象
      targetSource.releaseTarget(target);
    }
    if(setProxyContext) {
      //将当前代理对象设置到  currentProxy 的 ThreadLocal 中
      AopContext.setCurrentProxy(oldProxy);
    }
  }
}

使用自动代理(autoproxy)

"自动代理"表示,只需要在Spring中添加某个 Bean,这个 Bean 一个 BeanPostProcessor,那么Spring在每创建一个 Bean 时,都会经过这个BeanPostProcessor的判断,去判断当前正在创建的这个 Bean 需不需要进行AOP。

BeanNameAutoProxyCreator

import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;

@ComponentScan(basePackages = {"com.gongj.aop"})
public class AppConfig {

	@Bean
	public BeanNameAutoProxyCreator creator() {
		BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
		//可以传入多个beanName 需要被增强的目标类
		beanNameAutoProxyCreator.setBeanNames("gongService");
		//可以传入多个beanName  advisor
		beanNameAutoProxyCreator.setInterceptorNames("myCustomizeAdvisor");
		return beanNameAutoProxyCreator;
	}
}

有了这个Bean之后,可以自动的对setBeanNames中所对应的 bean 进行代理,代理逻辑为所设置的 interceptorNames

然后将我们之前自定义的MyCustomizeAdvisor、目标类GongService都加上@Component注解,将它注册到Spring中。

  • 启动类
public static void main(String[] args) {
    AnnotationConfigApplicationContext context =
        new AnnotationConfigApplicationContext(AppConfig.class);
    //获得代理对象
    YuanInterface yuanInterface = context.getBean("gongService", YuanInterface.class);
    yuanInterface.getUserInfo("程序员小杰");
    System.out.println(yuanInterface.getClass().getName());
}

结果:
方法之前执行
方法执行 = 程序员小杰
方法执行 = 程序员小杰
com.sun.proxy.$Proxy10

实现的效果与使用ProxyFactory时一致的。那我们先在来看看BeanNameAutoProxyCreator是如何实现的。

结构图

image-20210925115255938.png

从结构图我们可以知道BeanNameAutoProxyCreator是一个 BeanPostProcessor。而 AOP 的执行的逻辑在初始化后(如果有循环依赖会提前)。那我们直接找到处理 AOP的初始化后方法。改方法位于 org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
  if(bean != null) {
    Object cacheKey = getCacheKey(bean.getClass(), beanName);
    // earlyProxyReferences中存的是那些提前进行了AOP的bean,beanName:原始对象
    if(this.earlyProxyReferences.remove(cacheKey) != bean) {
      // 没有提前进行过AOP,则进行AOP
      return wrapIfNecessary(bean, beanName, cacheKey);
    }
  }
  //不需要进行 AOP 则返回原始对象
  return bean;
}

本文所述例子并没有产生循环依赖,所以不会提前进行 AOP。具体逻辑在 wrapIfNecessary方法中。

wrapIfNecessary

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
  // 在当前targetSourcedBeans中存在的bean,表示在实例化之前就产生了代理对象
  // 直接返回,那就不要再次产生代理对象了
  if(StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(
      beanName)) {
    return bean;
  }
  // advisedBeans 是一个 map, 存储的是 class:是否应该被代理,为true则需要被代理
  // 当前这个bean不用被代理
  if(Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
    return bean;
  }
  // 如果是普通bean,或者继承 Advisor、Pointcut、Advice
  //AopInfrastructureBean 的类不需要被代理
  if(isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(),
      beanName)) {
    // 将当前 cacheKey 标记为不用被代理
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
  }
  // 获取当前 beanClass 所匹配的 advisors >1
  Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(),
    beanName, null);
  // 如果匹配的advisors不等于null,那么则进行代理,并返回代理对象
  if(specificInterceptors != DO_NOT_PROXY) {
    // 将当前 cacheKey 标记为 需要被代理
    this.advisedBeans.put(cacheKey, Boolean.TRUE);
    // 基于bean对象和Advisor创建代理对象  >2
    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;
}

上述代码不是很复杂,看文章注释应该就能看懂了。那我们看看标注点 >1,寻找advisors

getAdvicesAndAdvisorsForBean

protected abstract Object[] getAdvicesAndAdvisorsForBean(Class <? > beanClass,
  String beanName, @Nullable TargetSource customTargetSource) throws BeansException;

由子类进行具体的实现。从结构图可知BeanNameAutoProxyCreator就是它的子类。

protected Object[] getAdvicesAndAdvisorsForBean(Class <? > beanClass, String beanName, @
  Nullable TargetSource targetSource) {
  if(this.beanNames != null) {
    for(String mappedName: this.beanNames) {
        //判断是不是 FactoryBean
      if(FactoryBean.class.isAssignableFrom(beanClass)) {
         //判断设置的 beanName是不是以 &开头 
        if(!mappedName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
          continue;
        }
        mappedName = mappedName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
      }
      if(isMatch(beanName, mappedName)) {
        // 根据当前 beanName 与 手动设置的beanName进行匹配,如果匹配,就会返回 new Object[0]
        // 后续会对当前beanName进行代理
        return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
      }
      BeanFactory beanFactory = getBeanFactory();
      if(beanFactory != null) {
        //上述逻辑没有符合,那就找到别名进行匹配
        String[] aliases = beanFactory.getAliases(beanName);
        for(String alias: aliases) {
          if(isMatch(alias, mappedName)) {
            return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
          }
        }
      }
    }
  }
  //返回 null
  return DO_NOT_PROXY;
}

beanNames就是我们在构建BeanNameAutoProxyCreator对象之后,手动设置的。 上述逻辑也挺简单的,如果匹配成功则返回 new Object[0],代表当前 bean 需要进行代理。返回 null,则不需要被代理。

createProxy

看看标记点 2的逻辑,是如何创建代理对象的。

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();
  // 从this复制配置参数
  proxyFactory.copyFrom(this);
    
  // 是否指定了必须用 cglib 进行代理,默认 false
  if(!proxyFactory.isProxyTargetClass()) {
    // 如果没有指定,那么则判断是不是应该进行cglib代理
	// 判断BeanDefinition中是否指定 
	// org.springframework.aop.framework.autoproxy.AutoProxyUtils.preserveTargetClass 
	// 如果为true,则使用 CGLIB代理
    if(shouldProxyTargetClass(beanClass, beanName)) {
      proxyFactory.setProxyTargetClass(true);
    }
    else {
      // 是否进行jdk动态代理,判断beanClass有没有实现接口
      evaluateProxyInterfaces(beanClass, proxyFactory);
    }
  }
  Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
  // 向ProxyFactory中添加advisor
  proxyFactory.addAdvisors(advisors); 
  // 被代理的对象
  proxyFactory.setTargetSource(targetSource); 
  customizeProxyFactory(proxyFactory);
  proxyFactory.setFrozen(this.freezeProxy);
  if(advisorsPreFiltered()) {
    proxyFactory.setPreFiltered(true);
  }
  // 生成代理对象
  return proxyFactory.getProxy(getProxyClassLoader());
}

看到了这里各位小伙伴应该会感到很熟悉了,我们看到了 ProxyFactory对象。所以这个方法就是给ProxyFactory对象的属性进行赋值,然后调用 proxyFactory.getProxy创建代理对象。

下面将单独讲讲几个方法,shouldProxyTargetClass方法有点简单, 不再阐述。

evaluateProxyInterfaces
protected void evaluateProxyInterfaces(Class <? > beanClass, ProxyFactory proxyFactory) {
  // 获得当前类及父类上所有的接口
  Class <? > [] targetInterfaces = ClassUtils.getAllInterfacesForClass(
    beanClass, getProxyClassLoader());
  boolean hasReasonableProxyInterface = false;
  // 遍历所有的接口,并进行过滤
  for(Class <? > ifc: targetInterfaces) {
    // 如果不是InitializingBean、DisposableBean、AutoCloseable等等接口
	// 接口的 ClassName 不能是 groovy.lang.GroovyObject 
	// 或者不能是 .cglib.proxy.Factory 、.bytebuddy.MockAccess结尾
	// 如果接口存在方法
    if(!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(
        ifc) && ifc.getMethods().length > 0) {
      //有接口不符合上述过滤条件
      hasReasonableProxyInterface = true;
      break;
    }
  }
  // 如果beanClass实现了可进行代理的接口
  if(hasReasonableProxyInterface) {
    for(Class <? > ifc: targetInterfaces) {
      // 将实现的接口添加到 proxyFactory 中
      proxyFactory.addInterface(ifc);
    }
  } else {
    // 如果不存在,则还是使用cglib代理
    proxyFactory.setProxyTargetClass(true);
  }
}

判断当前类及其父类实现的接口是否合规,实现对的接口不能为 InitializingBeanDisposableBean等等容器内部回调接口,接口的名称也不能为 groovy.lang.GroovyObject 等等名称,实现的接口需要有方法。如果没有合适的接口,proxyTargetClass 还是设置为 true ,还是使用 cglib 代理。

buildAdvisors
protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
  // 解析注册的所有interceptorName
  // 获取AbstractAutoProxyCreator手动setInterceptorNames()所设置的Interceptors
  // 因为是设置在AbstractAutoProxyCreator上的,所以是公用的
  Advisor[] commonInterceptors = resolveInterceptorNames();
  List < Object > allInterceptors = new ArrayList < > ();
  // 只有当specificInterceptors不为null时,allInterceptors中才会有值,最终才会进行代理
  if(specificInterceptors != null) {
    //加入到 allInterceptors 中
    allInterceptors.addAll(Arrays.asList(specificInterceptors));
    if(commonInterceptors.length > 0) {
      //applyCommonInterceptorsFirst 默认值为 true
      if(this.applyCommonInterceptorsFirst) {
        //将手动配置的也加入到 allInterceptors 中,并且是放在第一位
        allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
      } else {
        allInterceptors.addAll(Arrays.asList(commonInterceptors));
      }
    }
  }
  if(logger.isTraceEnabled()) {
    int nrOfCommonInterceptors = commonInterceptors.length;
    int nrOfSpecificInterceptors = (specificInterceptors != null ?
      specificInterceptors.length : 0);
    logger.trace("Creating implicit proxy for bean '" + beanName + "' with " +
      nrOfCommonInterceptors + " common interceptors and " +
      nrOfSpecificInterceptors + " specific interceptors");
  }
  Advisor[] advisors = new Advisor[allInterceptors.size()];
  for(int i = 0; i < allInterceptors.size(); i++) {
    //包装为 Advisor
    advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
  }
  return advisors;
}

将找到的advisors与手动设置的advisors放到一起,之后统一进行代理。至于 proxyFactory.getProxy这个开篇就介绍过了。然后执行代理逻辑的流程跟开篇分析的是一致的。

DefaultAdvisorAutoProxyCreator

DefaultAdvisorAutoProxyCreator 这个更加强大,只要添加了这个 Bean,它就会自动识别所有的 Advisor中的 PointCut进行代理。

结构图

image-20210925165527599.png

DefaultAdvisorAutoProxyCreator也是继承AbstractAdvisorAutoProxyCreator 类,而AbstractAdvisorAutoProxyCreator继承了AbstractAutoProxyCreator 类,所以这也是一个 BeanPostProcessor。所以也会进入到初始化后的逻辑中。

可以如此使用,使用DefaultAdvisorAutoProxyCreator就不需要手动指定代理对象和Advisor,它自动帮我们找到。

@Bean
public DefaultAdvisorAutoProxyCreator proxyCreator(){
    DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();
    return proxyCreator;
}

逻辑和 BeanNameAutoProxyCreator大体是一致的,都会进入到wrapIfNecessary方法。只不过只是在寻找Advices 有所区别。

getAdvicesAndAdvisorsForBean

在使用BeanNameAutoProxyCreator的时候,BeanNameAutoProxyCreator重写了这个方法。那本次使用了DefaultAdvisorAutoProxyCreator类,但是DefaultAdvisorAutoProxyCreator并没有进行具体的实现,而是由其父类AbstractAdvisorAutoProxyCreator重写了这个方法。

@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(Class <?> beanClass, String beanName, @
  Nullable TargetSource targetSource) {
  // 针对当前bean查找合格的Advisor
  List <Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
  if(advisors.isEmpty()) {
    return DO_NOT_PROXY;
  }
  return advisors.toArray();
}

findEligibleAdvisors

protected List <Advisor> findEligibleAdvisors(Class <? > beanClass, String beanName) {
  // 得到所有类型为 Advisor 的 Bean >1
  List < Advisor > candidateAdvisors = findCandidateAdvisors();
  // 得到和beanClass匹配的Advisor  >2
  List < Advisor > eligibleAdvisors = findAdvisorsThatCanApply(
    candidateAdvisors, beanClass, beanName);
  //提供给子类额外去添加 Advisor
  extendAdvisors(eligibleAdvisors);
  if(!eligibleAdvisors.isEmpty()) {
    //根据 order 进行排序
    eligibleAdvisors = sortAdvisors(eligibleAdvisors);
  }
  // 返回匹配的Advisor
  return eligibleAdvisors;
}

先看标记点1,看它是如何找到所有 Advisor类型的 Bean。

findCandidateAdvisors
protected List<Advisor> findCandidateAdvisors() {
    Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
    return this.advisorRetrievalHelper.findAdvisorBeans();
}

//再调用 findAdvisorBeans 方法
    
public List <Advisor> findAdvisorBeans() {
  
  String[] advisorNames = this.cachedAdvisorBeanNames;
  //是否有缓存
  if(advisorNames == null) {
    //查找 Advisor 类型的 beanName,平常说的 byType
    advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory,
      Advisor.class, true, false);
    this.cachedAdvisorBeanNames = advisorNames;
  }
  if(advisorNames.length == 0) {
    return new ArrayList < > ();
  }
  List <Advisor> advisors = new ArrayList <> ();
  for(String name: advisorNames) {
    if(isEligibleBean(name)) {
      //确定指定的bean当前是否正在创建中。
      if(this.beanFactory.isCurrentlyInCreation(name)) {
        if(logger.isTraceEnabled()) {
          logger.trace("Skipping currently created advisor '" + name + "'");
        }
      } else {
        try {
          // 根据 beanName 获取Advisor类型的bean
          advisors.add(this.beanFactory.getBean(name, Advisor.class));
        } catch(BeanCreationException ex) {
          Throwable rootCause = ex.getMostSpecificCause();
          if(rootCause instanceof BeanCurrentlyInCreationException) {
            BeanCreationException bce = (BeanCreationException) rootCause;
            String bceBeanName = bce.getBeanName();
            if(bceBeanName != null && this.beanFactory.isCurrentlyInCreation(
                bceBeanName)) {
              if(logger.isTraceEnabled()) {
                logger.trace("Skipping advisor '" + name +
                  "' with dependency on currently created bean: " + ex.getMessage()
                );
              }
              // Ignore: indicates a reference back to the bean we're trying to advise.
              // We want to find advisors other than the currently created bean itself.
              continue;
            }
          }
          throw ex;
        }
      }
    }
  }
  return advisors;
}    

看着代码挺多,但重要逻辑就那一两句。

  • 根据 Advisor类型获得所有 beanName
  • 根据 beanName 获得 Advisor类型的bean
  • 将 bean 添加到 advisors中并返回
findAdvisorsThatCanApply

标记点2 的代码比较复杂,理解它干了什么事情就好了。

protected List <Advisor> findAdvisorsThatCanApply(List < Advisor >
  candidateAdvisors, Class <?> beanClass, String beanName) {
  ProxyCreationContext.setCurrentProxiedBeanName(beanName);
  try {
    // 在所有Advisor中筛选和beanClass匹配的Advisor
    return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
  } finally {
    ProxyCreationContext.setCurrentProxiedBeanName(null);
  }
}
findAdvisorsThatCanApply
public static List <Advisor> findAdvisorsThatCanApply(List < Advisor >
  candidateAdvisors, Class <? > clazz) {
  if(candidateAdvisors.isEmpty()) {
    return candidateAdvisors;
  }
  List <Advisor> eligibleAdvisors = new ArrayList < > ();
  for(Advisor candidate: candidateAdvisors) {
    // IntroductionAdvisor 这个用的少了,可以忽略
    if(candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
      eligibleAdvisors.add(candidate);
    }
  }
  boolean hasIntroductions = !eligibleAdvisors.isEmpty();
  for(Advisor candidate: candidateAdvisors) {
    if(candidate instanceof IntroductionAdvisor) {
      // already processed
      continue;
    }
     //不搞什么其他七七八八的 会进入到这里
    if(canApply(candidate, clazz, hasIntroductions)) {
      eligibleAdvisors.add(candidate);
    }
  }
  return eligibleAdvisors;
}

重点方法 canApply

canApply
public static boolean canApply(Advisor advisor, Class <?> targetClass, boolean hasIntroductions) {
    // IntroductionAdvisor 这个用的少了,可以忽略
  if(advisor instanceof IntroductionAdvisor) {
    return((IntroductionAdvisor) advisor).getClassFilter().matches(
      targetClass);
  } else if(advisor instanceof PointcutAdvisor) {
      //重点看 PointcutAdvisor 我们所举得的例子就是实现了它
    PointcutAdvisor pca = (PointcutAdvisor) advisor;
    // 获取Pointcut跟targetClass做匹配
    return canApply(pca.getPointcut(), targetClass, hasIntroductions);
  } else {
    // It doesn't have a pointcut so we assume it applies.
    return true;
  }
}

再调用 canApply方法,传人 Pointcut和目标对象。

public static boolean canApply(Pointcut pc, Class <? > targetClass, boolean hasIntroductions) {
  Assert.notNull(pc, "Pointcut must not be null");
  if(!pc.getClassFilter().matches(targetClass)) {
    return false;
  }
  // 我们手动设置的切点 methodPointcut.addMethodName("getUserInfo");
  MethodMatcher methodMatcher = pc.getMethodMatcher();
  if(methodMatcher == MethodMatcher.TRUE) {
    // No need to iterate the methods if we're matching any method anyway...
    return true;
  }
  IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
  if(methodMatcher instanceof IntroductionAwareMethodMatcher) {
    introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
  }
  Set < Class <? >> classes = new LinkedHashSet < > ();
  if(!Proxy.isProxyClass(targetClass)) {
    classes.add(ClassUtils.getUserClass(targetClass));
  }
  classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
  // 遍历targetClass以及 targetClass的父类和接口中的所有方法
  for(Class <? > clazz: classes) {
    Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
    for(Method method: methods) {
      if(introductionAwareMethodMatcher != null ?
        introductionAwareMethodMatcher.matches(method, targetClass,
          hasIntroductions) : methodMatcher.matches(method, targetClass)) {
        return true;
      }
    }
  }
  return false;
}

获得我们所设置的切点与目标对象以及目标对象的父类和接口中的所有方法进行匹配,如果匹配成功,则说明当前类需要被代理。这就是 DefaultAdvisorAutoProxyCreator的流程。

使用@EnableAspectJAutoProxy

上面讲了使用 ProxyFactoryBeanNameAutoProxyCreatorDefaultAdvisorAutoProxyCreator分别来使用 AOP,但那几种方式都不是我们工作当中使用,那工作当中我们是怎么使用的呢?本章节为各位小伙伴讲解的 EnableAspectJAutoProxy注解。

我们先看看@EnableAspectJAutoProxy注解的源码

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

    //是否强制采用CGLIB创建代理对象
    //默认为 false
	boolean proxyTargetClass() default false;

    //是否暴露代理对象,用来解决同一个目标类中,方法互相调用时代理不生效的问题
	boolean exposeProxy() default false;

}

EnableAspectJAutoProxy里面就两个属性,这两个属性应该都不会感到陌生,在源码中经常见到这两个属性。

在其类定义上有一个非常重要的注解,@Import(AspectJAutoProxyRegistrar.class) ,导入配置类。

AspectJAutoProxyRegistrar

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
}

AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrar接口,那就说明AspectJAutoProxyRegistrar本身不会被注册为 Bean 定义,但是其registerBeanDefinitions方法可用于注册 Bean定义。

那就一起来详细的来看看 registerBeanDefinitions方法。

@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
  BeanDefinitionRegistry registry) {
  //  如果需要注册,则注册一个类型为
  //  AnnotationAwareAspectJAutoProxyCreator 的自动代理创建者的bean定义
  AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
    registry);
  //获取@EnableAspectJAutoProxy注解的属性集合
  AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(
    importingClassMetadata, EnableAspectJAutoProxy.class);
  if(enableAspectJAutoProxy != null) {
    //如果 proxyTargetClass 属性为 true
    if(enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
      //配置创建代理方式为 CGLIB
      AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
    }
    //如果 exposeProxy 属性为 true
    if(enableAspectJAutoProxy.getBoolean("exposeProxy")) {
      //配置需要暴露代理对象
      AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
    }
  }
}

看了上述方法的逻辑,那就知道了它会注册一个类型为AnnotationAwareAspectJAutoProxyCreator的 Bean 定义。那就一起来看看AnnotationAwareAspectJAutoProxyCreator这个类。

AnnotationAwareAspectJAutoProxyCreator

结构图

image-20210925190038390.png

从结构图我们能了解到,它也是 AbstractAutoProxyCreator的子类,并且也是BeanPostProcessor。那为什么要添加一个 AnnotationAwareAspectJAutoProxyCreator类呢,直接添加DefaultAdvisorAutoProxyCreator不香吗?

既然使用 AnnotationAwareAspectJAutoProxyCreator,那肯定有更强大的功能。

AnnotationAwareAspectJAutoProxyCreator继承了AspectJAwareAdvisorAutoProxyCreator,重写了findCandidateAdvisors()方法,它既可以找到Advisor类型的 bean,也能把所有@Aspect注解标注的类扫描出来并生成Advisor

findCandidateAdvisors

@Override
protected List < Advisor > findCandidateAdvisors() {
 // 调用父类方法,获得所有类型为 Advisor 的 bean
  List <Advisor> advisors = super.findCandidateAdvisors();
  
  // 找的是通过AspectJ的方式定义的Advisor
  if(this.aspectJAdvisorsBuilder != null) {
    advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
  }
  return advisors;
}

buildAspectJAdvisors

public List < Advisor > buildAspectJAdvisors() {
  List < String > aspectNames = this.aspectBeanNames;
  if(aspectNames == null) {
    synchronized(this) {
      aspectNames = this.aspectBeanNames;
      if(aspectNames == null) {
        List < Advisor > advisors = new ArrayList < > ();
        aspectNames = new ArrayList < > ();
        // 拿到 beanFactory 中所有的bean
        String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
          this.beanFactory, Object.class, true, false);
        for(String beanName: beanNames) {
          // 是不是一个合格的Aspect的beanName
          if(!isEligibleBean(beanName)) {
            continue;
          }
          //根据 beanName 获得类的Class
          Class <?> beanType = this.beanFactory.getType(beanName);
          if(beanType == null) {
            continue;
          }
          //判断类上是否存在@Aspect注解
          if(this.advisorFactory.isAspect(beanType)) {
             //进行缓存
            aspectNames.add(beanName);
            AspectMetadata amd = new AspectMetadata(beanType, beanName);
            if(amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
              MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(
                this.beanFactory, beanName);
              // 解析Advisor (解析@Befor,@After这些注解)  》1
              List < Advisor > classAdvisors = this.advisorFactory.getAdvisors(
                factory);
              if(this.beanFactory.isSingleton(beanName)) {
                this.advisorsCache.put(beanName, classAdvisors);
              } else {
                this.aspectFactoryCache.put(beanName, factory);
              }
              advisors.addAll(classAdvisors);
            } else {
              // Per target or per this.
              if(this.beanFactory.isSingleton(beanName)) {
                throw new IllegalArgumentException("Bean with name '" +
                  beanName +
                  "' is a singleton, but aspect instantiation model is not singleton"
                );
              }
              MetadataAwareAspectInstanceFactory factory = new PrototypeAspectInstanceFactory(
                this.beanFactory, beanName);
              this.aspectFactoryCache.put(beanName, factory);
              advisors.addAll(this.advisorFactory.getAdvisors(factory));
            }
          }
        }
        this.aspectBeanNames = aspectNames;
        return advisors;
      }
    }
  }
  if(aspectNames.isEmpty()) {
    return Collections.emptyList();
  }
  List < Advisor > advisors = new ArrayList < > ();
  for(String aspectName: aspectNames) {
    List < Advisor > cachedAdvisors = this.advisorsCache.get(aspectName);
    if(cachedAdvisors != null) {
      advisors.addAll(cachedAdvisors);
    } else {
      MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(
        aspectName);
      advisors.addAll(this.advisorFactory.getAdvisors(factory));
    }
  }
  return advisors;
}
getAdvisors

具体实现在ReflectiveAspectJAdvisorFactory类中。

@Override
public List < Advisor > getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
  //获得被 @Aspect 标注的类对象
  Class <?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
  String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
  validate(aspectClass);
  
  MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(
    aspectInstanceFactory);
  List < Advisor > advisors = new ArrayList < > ();
  // 遍历所有非@PointCut的方法,获取@Before、@After等注解中的表达式切点,加上当前方法(也就是代理逻辑)一起封装为一个Advisor 
  for(Method method: getAdvisorMethods(aspectClass)) {  //> 1
    Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory,
      advisors.size(), aspectName); // > 2
    if(advisor != null) {
      advisors.add(advisor);
    }
  }
  if(!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata()
    .isLazilyInstantiated()) {
    Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(
      lazySingletonAspectInstanceFactory);
    advisors.add(0, instantiationAdvisor);
  }
  // Find introduction fields.
  // 处理DeclareParents注解
  for(Field field: aspectClass.getDeclaredFields()) {
    Advisor advisor = getDeclareParentsAdvisor(field);
    if(advisor != null) {
      advisors.add(advisor);
    }
  }
  return advisors;
}
getAdvisorMethods

@Pointcut标注的方法进行排除。

private List<Method> getAdvisorMethods(Class<?> aspectClass) {
    final List<Method> methods = new ArrayList<>();
    // 遍历所有方法,把不存在@Pointcut注解的方法返回
    ReflectionUtils.doWithMethods(aspectClass, method -> {
        // Exclude pointcuts
        if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
            methods.add(method);
        }
    }, ReflectionUtils.USER_DECLARED_METHODS);
    methods.sort(METHOD_COMPARATOR);
    return methods;
}
getAdvisor
@Override@ Nullable
public Advisor getAdvisor(Method candidateAdviceMethod,
  MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrderInAspect,
  String aspectName) {
  validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
  // 得到当前candidateAdviceMethod方法上的所定义的 expression 表达式,也就是切点
  AspectJExpressionPointcut expressionPointcut = getPointcut(
    candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass()
  );
  if(expressionPointcut == null) {
    return null;
  }
  // 构造一个Advisor,封装了切点表达式和当前方法
  return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut,
    candidateAdviceMethod, this, aspectInstanceFactory,
    declarationOrderInAspect, aspectName);
}

上述逻辑就是AnnotationAwareAspectJAutoProxyCreator寻找Advisor的过程。

注解和源码对应关系

1、@Before对应的是AspectJMethodBeforeAdvice,直接实现MethodBeforeAdvice,在进行动态代理时会把AspectJMethodBeforeAdvice转成MethodBeforeAdviceInterceptor,也就转变成了MethodBeforeAdviceInterceptor

    1. 先执行advice对应的方法
    2. 再执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法

2、@After对应的是AspectJAfterAdvice,直接实现了MethodInterceptor

    1. 先执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法
    2. 再执行advice对应的方法

3、@Around对应的是AspectJAroundAdvice,直接实现了MethodInterceptor

    1. 直接执行advice对应的方法

4、@AfterThrowing对应的是AspectJAfterThrowingAdvice,直接实现了MethodInterceptor

    1. 先执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法
    2. 如果上面抛了Throwable,那么则会执行advice对应的方法

5、@AfterReturning 对应的是AspectJAfterReturningAdvice,实现了AfterReturningAdvice,在进行动态代理时会把AspectJAfterReturningAdvice转成AfterReturningAdviceInterceptor,也就转变成了MethodInterceptor

    1. 先执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法
    2. 执行上面的方法后得到最终的方法的返回值
    1. 再执行Advice对应的方法

使用

@Aspect
@Component
public class AspectConfig {

	//对 findById 方法进行增强
	@Before("execution(public * com.gongj.aop.GongService.findById(..))")
	public void beforeConfig(){
		System.out.println("======beforeConfig==================");
	}

	@After("execution(public * com.gongj.aop.GongService.findById(..))")
	public void afterConfig(){
		System.out.println("======afterConfig==================");
	}
}

image-20210925193709025.png

  • 启动类
public static void main(String[] args) {
    AnnotationConfigApplicationContext context =
        new AnnotationConfigApplicationContext(AppConfig.class);
    //获得代理对象
    YuanInterface yuanInterface = context.getBean("gongService", YuanInterface.class);
    yuanInterface.getUserInfo("程序员小杰");

    yuanInterface.findById(5L);
    System.out.println(yuanInterface.getClass().getName());
}

结果:
方法之前执行
方法执行 = 程序员小杰
方法执行 = 程序员小杰
======beforeConfig==================
方法执行 = 5
======afterConfig==================
com.sun.proxy.$Proxy20

  • 如你对本文有疑问或本文有错误之处,欢迎评论留言指出。如觉得本文对你有所帮助,欢迎点赞和关注。