Spring AOP

15

使用

代理模式就是为其他对象提供一种代理以控制对这个对象的访问,增强一个类中的方法对程序进行扩展,现在常用的动态代理分为cglib和jdk的动态代理

ProxyFactory

当然我们的重点是spring,可以使用spring的代理工厂,内部是基于责任链模式设计的

使用了Advice接口,我们就不需要手动去执行代码了,spring的ProxyFactory自动会我们执行指定的AOP代码

在实际执行的时候,spring会将所有通知都封装为MethodInterceptor

  • MethodBeforeAdvice 前置通知,实现before方法

  • AfterReturningAdvice 返回通知,实现afterReturning方法

  • ThrowsAdvice 异常通知,比较特殊

  • MethodInterceptor 环绕通知,实现invoke方法

// 目标对象
UserService target = new UserService();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(target);
// spring内部默认使用cglib进行动态代理,所以不需要接口
// proxyFactory.setInterfaces(UserService.class);
// 责任链模式
// proxyFactory.addAdvice(new MengnanThrowsAdvice());
// proxyFactory.addAdvice(new MengnanAroundAdvice());
// proxyFactory.addAdvice(new MengnanBeforeAdvice());
// proxyFactory.addAdvice(new MengnanAfterReturningAdvice());
// 除了执行addAdvice也可以执行addAdvisor
// addAdvisor = Pointcut + Advice
proxyFactory.addAdvisor(new PointcutAdvisor() {
  @Override
  // 切入点
  public Pointcut getPointcut() {
    return new StaticMethodMatcherPointcut() {
      @Override
      public boolean matches(Method method, Class<?> targetClass) {
        return targetClass.equals(UserService.class);// 匹配才会执行代理逻辑
      }
    };
  }
  @Override
  // 执行前置通知
  public Advice getAdvice() {
    return new MengnanBeforeAdvice();
  }
});
UserService proxy = (UserService) proxyFactory.getProxy();
proxy.testA();

异常通知比较特殊,ThrowsAdvice是一个空接口,继承它不需要实现任何方法,需要我们自己实现afterThrowing方法

先不考虑背后的原理,这么设计的好处显而易见,可以通过一个参数捕获指定异常,不过这样的话接口无法明确定义

接口注释上详细说明了可以实现的方法签名

  • public void afterThrowing(Exception ex)

  • public void afterThrowing(RemoteException)

  • public void afterThrowing(Method method, Object[] args, Object target, Exception ex)

  • public void afterThrowing(Method method, Object[] args, Object target, ServletException ex)

public class MengnanThrowsAdvice implements ThrowsAdvice {
​
  // 最后一个参数是NullPointerException,所以只能捕获NullPointerException
  public void afterThrowing(Method method, Object[] args, Object target, NullPointerException ex) {
    System.out.println("方法执行出现异常!");
  }
}

ProxyFactoryBean

ProxyFactory只是一个工具,可以使用ProxyFactoryBean搭配spring的ioc一起使用

@Bean
// 注意不要和userService对象重名
public ProxyFactoryBean userService() {
  UserService userService = new UserService();
  ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
  proxyFactoryBean.addAdvice(new MengnanBeforeAdvice());
  proxyFactoryBean.setTarget(userService);
  return proxyFactoryBean;
}

BeanNameAutoProxyCreator

自动代理创建器,内部是基于beanPostProcessor

@Bean
public BeanNameAutoProxyCreator beanNameAutoProxyCreator() {
  BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
  // 类名通配符
  beanNameAutoProxyCreator.setBeanNames("user*");
  // 匹配拦截器名称
  beanNameAutoProxyCreator.setInterceptorNames("mengnanAroundAdvice");
  return beanNameAutoProxyCreator;
}

DefaultPointcutAdvisor

只要当前类匹配就自动会对这个类进行动态代理,需要搭配DefaultAdvisorAutoProxyCreator使用

@Bean
// 可以看到这个类和spring中最常用的切面类aspect的使用方式几乎一致,所以DefaultAdvisorAutoProxyCreator源码非常重要
public DefaultPointcutAdvisor defaultPointcutAdvisor() {
  NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut();
  // 是否有test方法
  pointcut.addMethodName("test");
  DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor();
  defaultPointcutAdvisor.setPointcut(pointcut);
  // 会执行MengnanBeforeAdvice的代理
  defaultPointcutAdvisor.setAdvice(new MengnanBeforeAdvice());
  return defaultPointcutAdvisor;
}
​
@Bean
// 也可以将@Import(DefaultAdvisorAutoProxyCreator.class)写在类上效果一致
// 内部会将所有Advisor的Bean找出来
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
  return new DefaultAdvisorAutoProxyCreator();
}

注解

注解也是项目中最常用的使用方式

在spring项目中使用aspectj相关注解需要单独引入

dependencies {
  implementation(project(":spring-context"))
  implementation(project(":spring-aop"))
   // 如果你想使用aspectj相关的注解,你需要单独引入aspectj相关的jar包
   implementation group: 'org.aspectj', name: 'aspectjrt', version: '1.9.5'
   implementation group: 'org.aspectj', name: 'aspectjweaver', version: '1.9.5'
}

配置类中添加该注解@EnableAspectJAutoProxy

切面类

有如下几种注解

  • @Before

  • @After

  • @Around

  • @AfterReturning

  • @AfterThrowing

aspectj是在编译器通过(ajc命令)直接对代码进行增强,然而spring的aop不是,我们还是只需要通过javac进行编译

@Aspect
@Component
// spring解析到该Bean上添加了@Aspect,就知道这是一个切面类
// 开始解析@Before为Pointcut对象,并通过方法得到Advice对象,最后生成Advisor对象
// spring只是内部使用了Aspect的注解,但是底层并没有依靠aspectj而是自己实现
public class MengnanAspect {
  @Before("execution(public void info.mengnan.service.UserService.test())")
  public void mengnanBefore() {
    System.out.println("mengnanBefore");
  }
}

通过以上几种方式中的一种,就可以从ioc容器中直接获取代理对象

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
// 从spring中获取代理了UserService的ProxyFactoryBean,执行代理逻辑
// 或者使用BeanNameAutoProxyCreator自动从spring获取被代理的对象和Advice实现代理
UserService userService = context.getBean("userService", UserService.class);
userService.test();

源码

ProxyFactory

ProxyFactory内部会将userService封装为一个TargetSource,TargetSource就是被代理对象

当我们执行完切面逻辑后会通过getTarget拿到被代理对象并执行方法

UserService userService = new UserService();
ProxyFactory proxyFactory = new ProxyFactory();
// 设置代理对象
proxyFactory.setTarget(userService);
// 添加切面逻辑
proxyFactory.addAdvice(new MengnanAfterReturningAdvice());
// 获取代理对象
UserService proxy = (UserService) proxyFactory.getProxy();

执行getProxy最终会执行createAopProxy方法,spring为我们自动选择是使用jdk的动态代理还是cglib的动态代理

其中就有对应的2个实现类

  • JdkDynamicAopProxy

  • ObjenesisCglibAopProxy

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
  // 如果你在ProxyFactory设置optimize为true,需要更好的性能
  // ProxyFactory的proxyTargetClass设置为true并且@EnableAspectJAutoProxy的属性proxyTargetClass为false(默认为false)
  // ProxyFactory没有addInterface
  if (config.isOptimize() || config.isProxyTargetClass() || !config.hasUserSuppliedInterfaces()) {
    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生成的代理类
    // 是否是lambda
    if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {
      return new JdkDynamicAopProxy(config);
    }
    return new ObjenesisCglibAopProxy(config);
  }
  else {
    return new JdkDynamicAopProxy(config);
  }
}
基于Cglib的动态代理
private Object buildProxy(@Nullable ClassLoader classLoader, boolean classOnly) {
  try {
    // 拿到被代理的类targetClass
    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();
      Class<?>[] additionalInterfaces = rootClass.getInterfaces();
      for (Class<?> additionalInterface : additionalInterfaces) {
        this.advised.addInterface(additionalInterface);
      }
    }
    validateClassIfNecessary(proxySuperClass, classLoader);
    // 创建cglib Enhancer
    Enhancer enhancer = createEnhancer();
    if (classLoader != null) {
      enhancer.setClassLoader(classLoader);
      if (classLoader instanceof SmartClassLoader smartClassLoader &&
          smartClassLoader.isClassReloadable(proxySuperClass)) {
        enhancer.setUseCache(false);
      }
    }
    // 被代理的类继承了代理类
    enhancer.setSuperclass(proxySuperClass);
    // 设置接口
    enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
    enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
    enhancer.setAttemptLoad(true);
    enhancer.setStrategy(KotlinDetector.isKotlinType(proxySuperClass) ?
        new ClassLoaderAwareGeneratorStrategy(classLoader) :
        new ClassLoaderAwareGeneratorStrategy(classLoader, undeclaredThrowableStrategy)
    );
    // 获取和被代理类所匹配的Advisor
    Callback[] callbacks = getCallbacks(rootClass);
    Class<?>[] types = new Class<?>[callbacks.length];
    for (int x = 0; x < types.length; x++) {
      types[x] = callbacks[x].getClass();
    }
    ProxyCallbackFilter filter = new ProxyCallbackFilter(
        this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset);
    enhancer.setCallbackFilter(filter);
    enhancer.setCallbackTypes(types);
    try {
      // classOnly为false返回创建代理对象
	  // classOnly一般情况下都为false
      return (classOnly ? createProxyClass(enhancer) : createProxyClassAndInstance(enhancer, callbacks));
    }
    finally {
      filter.advised.reduceToAdvisorKey();
    }
  }
  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) {
    throw new AopConfigException("Unexpected AOP exception", ex);
  }
}
基于jdk的动态代理
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 {
    // 如果接口中没有定义equals方法、hashCode方法则执行调用不走代理
    if (!this.cache.equalsDefined && AopUtils.isEqualsMethod(method)) {
      return equals(args[0]);
    }
    else if (!this.cache.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;
    // 如果ProxyFactory的exposeProxy属性设置为true
    if (this.advised.exposeProxy) {
      // 则会将代对象存储在ThreadLocal中
      // 如果是同一个线程可以通过AopContext.currentProxy()拿到代理对象
      // 可以通过这个方法测试是否是事物失效
      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);
    if (chain.isEmpty()) {
      Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
      // 为空,直接执行被代理对应方法
      retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
    }
    else {
      // 封装为MethodInvocation对象
      MethodInvocation invocation =
          new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
      // 执行代理逻辑
      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.class && returnType.isPrimitive()) {
      throw new AopInvocationException(
          "Null return value from advice does not match primitive return type for: " + method);
    }
    if (coroutinesReactorPresent && KotlinDetector.isSuspendingFunction(method)) {
      return COROUTINES_FLOW_CLASS_NAME.equals(new MethodParameter(method, -1).getParameterType().getName()) ?
          CoroutinesUtils.asFlow(retVal) : CoroutinesUtils.awaitSingleOrNull(retVal, args[args.length - 1]);
    }
    // 返回
    return retVal;
  }
  finally {
    if (target != null && !targetSource.isStatic()) {
      targetSource.releaseTarget(target);
    }
    if (setProxyContext) {
      AopContext.setCurrentProxy(oldProxy);
    }
  }
}

不论是jdk的动态代理还是cglib的动态代理都会经历2个步骤

  • 获取调用链路

  • 执行代理逻辑

获取调用链路

执行ProxyFactory创建代理之前,拿到所有的Advisor并进行封装,并和当前正在执行的方法进行匹配

2种代理模式都会执行该方法来获取往内部添加的advice

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
    Advised config, Method method, Class<?> targetClass) {
  AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
  // 找出所有的Advisor
  Advisor[] advisors = config.getAdvisors();
  List<Object> interceptorList = new ArrayList<>(advisors.length);
  Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
  Boolean hasIntroductions = null;
  // 遍历Advisor通过Pointcut找到符合的Advice
  // Advisor包含Pointcut + Advice
  // 如果只调用了addAdvice内部也会赋值一个默认的Pointcut(Pointcut.TRUE所有都匹配)
  for (Advisor advisor : advisors) {
    if (advisor instanceof PointcutAdvisor pointcutAdvisor) {
      // Pointcut内部需要实现getClassFilter(类匹配)和getMethodMatcher(方法匹配)方法
      // 先匹配类
      if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
        MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
        boolean match;
        // 再匹配方法
        if (mm instanceof IntroductionAwareMethodMatcher iamm) {
          if (hasIntroductions == null) {
            hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
          }
          match = iamm.matches(method, actualClass, hasIntroductions);
        }
        // 实现getMethodMatcher方法需要传递MethodMatcher对象
        // MethodMatcher需要传递MethodMatcher对象,MethodMatcher需要实现2个参数的matches方法
        // 如果为true说明匹配方法
        else {
          match = mm.matches(method, actualClass);
        }
        // 如果匹配方法
        if (match) {
          MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
          // MethodMatcher对象还需要实现,isRuntime和3个参数的matches方法
          // 这个matches方法可以在运行时传递的入参args是否匹配
          // 是否设置为运行时
          if (mm.isRuntime()) {
            for (MethodInterceptor interceptor : interceptors) {
              // 如果是运行时再封装一层 拦截器和动态方法匹配器
              interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
            }
          }
          else {
            interceptorList.addAll(Arrays.asList(interceptors));
          }
        }
        // 不匹配则忽略
      }
    }
    else if (advisor instanceof IntroductionAdvisor ia) {
      if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
        Interceptor[] interceptors = registry.getInterceptors(advisor);
        interceptorList.addAll(Arrays.asList(interceptors));
      }
    }
    else {
      Interceptor[] interceptors = registry.getInterceptors(advisor);
      interceptorList.addAll(Arrays.asList(interceptors));
    }
  }
  return interceptorList;
}

动态匹配

运行时匹配,使用DynamicMethodMatcherPointcut,这个时候isRuntime方法默认返回true

如果使用StaticMethodMatcherPointcut,isRuntime返回false,并且被final修饰

proxyFactory.addAdvisor(new PointcutAdvisor() {
  @Override
  public Pointcut getPointcut() {
    return new DynamicMethodMatcherPointcut() {
      @Override
      public boolean matches(Method method, Class<?> targetClass, Object... args) {
         return method.getName().equals("test");;
      }
    };
  }
  @Override
  public Advice getAdvice() {
    return new MengnanBeforeAdvice();
  }
});

执行代理逻辑

把和当前方法匹配的advised,调用ReflectiveMethodInvocation的构造方法,把和方法所匹配的Advisor封装成MethodInterceptor

最后执行ReflectiveMethodInvocation的proceed方法,执行各个MethodInterceptor以及被代理对象的对应方法

按顺序调用每个invoke方法,并通过this将当前MethodInterceptor继续传递到下一个代理逻辑中

执行完最后一个MethodInterceptor执行invokeJoinpoint,执行被代理对象的当前方法

public Object proceed() throws Throwable {
  // currentInterceptorIndex的初始值为-1
  // interceptorsAndDynamicMethodMatchers就是调用链路拦截器advised
  // 执行到最后一个执行被代理对象的方法
  if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
    return invokeJoinpoint();
  }
  // 取出第一个,并且执行自增操作,直到拿到最后一个
  Object interceptorOrInterceptionAdvice =
      this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
  // 是否继承了InterceptorAndDynamicMethodMatcher
  // 在获取调用链路发现methodMatcher的isRuntime代码中,如果为true就会封装为InterceptorAndDynamicMethodMatcher
  if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher dm) {
    // 根据方法动态进行匹配,如果匹配才会继续执行
    Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
    if (dm.matcher().matches(this.method, targetClass, this.arguments)) {
      return dm.interceptor().invoke(this);
    }
    else {
      // 否则跳过本链路
      return proceed();
    }
  }
  else {
    // 没有继承,执行MethodInterceptor的invoke方法(每个invoke方法内部都会执行proceed)
    // 如果是MethodBeforeAdviceInterceptor、AfterReturningAdviceInterceptor
    // 执行并进入调用链路(传递的是this)
    return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
  }
}