IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> SpringAOP底层API之代理对象执行流程 -> 正文阅读

[Java知识库]SpringAOP底层API之代理对象执行流程

我们之前说到了在对目标对象创建代理对象之前,如果我们使用是基于AspecJ模式的AspectJProxyFactory的代理工厂,那么spring会先解析aspect切面类,然后根据pointcut去判断并过滤出适用于目标对象的advisor,并把这些过滤出来的advisor形成一条调用链,目的是当我们的目标对象执行目标方法的时候对其进行拦截达到增强的作用,那么下面我们就来看一下spring通过advisor调用链对目标方法执行的时候去进行拦截的执行流程

这里讨论的是关于JDK的动态代理执行过程,所以我们直接来到JdkDynamicAopProxy这个类

org.springframework.aop.framework.JdkDynamicAopProxy#invoke

因为JdkDynamicAopProxy这个类不仅能产生代理对象,而且它里面还实现了代理对象的方法增强逻辑,因为它实现了InvocationHandler接口

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

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

   try {
       //当代理对象调用object的equals以及hashcode方法的时候直接放行不做增强处理
      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.
         //把代理对象放到ThreadLocal中
         //那么在整个线程的执行周期中可以调用AopContext.currentProxy得到当前类的代理对象
         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();
      //从targetSource中获取目标类targetclass
      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...
         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);
      }
   }
}

org.springframework.aop.framework.AdvisedSupport#getInterceptorsAndDynamicInterceptionAdvice

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
   MethodCacheKey cacheKey = new MethodCacheKey(method);
   //从缓存中判断是否存在这个方法的拦截链
   List<Object> cached = this.methodCache.get(cacheKey);
   //如果缓存没有,那么就去创建该方法的拦截链
   if (cached == null) {
       //从拦截链工厂中创建得到拦截链
      cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
            this, method, targetClass);
       //把方法的拦截链放到缓存中     
      this.methodCache.put(cacheKey, cached);
   }
   return cached;
}

org.springframework.aop.framework.DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice

该方法所做的就是对执行代理对象目标方法的时候去找出该目标方法所对应的拦截链

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

   // This is somewhat tricky... We have to process introductions first,
   // but we need to preserve order in the ultimate list.
   //得到一个AdvisorAdapterRegistry对象
   //这个对象是干嘛的?我们下面再去说
   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调用链
   for (Advisor advisor : advisors) {
      if (advisor instanceof PointcutAdvisor) {
         // Add it conditionally.
         PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
         if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
            MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
            boolean match;
            if (mm instanceof IntroductionAwareMethodMatcher) {
               if (hasIntroductions == null) {
                  hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
               }
               //调用pointcut的matches方法根据aspect表达式去判断该方法是否需要增强
               //如果match为true,那么就表示该advisor不但适用于该目标类而且使用于当前目标方法
               match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
            }
            else {
               match = mm.matches(method, actualClass);
            }
            if (match) {
                //match为true,证明这个方法需要被拦截增强
               MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
               if (mm.isRuntime()) {
                  // Creating a new object instance in the getInterceptors() method
                  // isn't a problem as we normally cache created chains.
                  for (MethodInterceptor interceptor : interceptors) {
                     interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                  }
               }
               else {
                  interceptorList.addAll(Arrays.asList(interceptors));
               }
            }
         }
      }
      else if (advisor instanceof IntroductionAdvisor) {
         IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
         if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
            Interceptor[] interceptors = registry.getInterceptors(advisor);
            interceptorList.addAll(Arrays.asList(interceptors));
         }
      }
      else {
         Interceptor[] interceptors = registry.getInterceptors(advisor);
         interceptorList.addAll(Arrays.asList(interceptors));
      }
   }

   return interceptorList;
}

org.springframework.aop.framework.adapter.DefaultAdvisorAdapterRegistry#getInterceptors

这个方法做的是把一个适用于目标方法的advisor转换成Interceptor

/**
* @advisor 这里传进来的advisor对象根据上面我们的理解就是一个适用于目标方法的advisor
*/
@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
   List<MethodInterceptor> interceptors = new ArrayList<>(3);
   //得到advisor所绑定的advice增强器
   Advice advice = advisor.getAdvice();
   //如果这个增强器是MethodInteceptor类型的,那么就直接加入到拦截链中
   if (advice instanceof MethodInterceptor) {
      interceptors.add((MethodInterceptor) advice);
   }
   //通过AdvisorAdapter去对advice进行适配,把advice转换成对应的拦截器MethodInteceptor
   //AdvisorAdapter的作用?
   for (AdvisorAdapter adapter : this.adapters) {
      if (adapter.supportsAdvice(advice)) {
         interceptors.add(adapter.getInterceptor(advisor));
      }
   }
   if (interceptors.isEmpty()) {
      throw new UnknownAdviceTypeException(advisor.getAdvice());
   }
   return interceptors.toArray(new MethodInterceptor[0]);
}

上面用到了AdvisorAdapter这个advisor适配器,那么这个适配器到底是干嘛用的呢?

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


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

public void registerAdvisorAdapter(AdvisorAdapter adapter) {
   this.adapters.add(adapter);
}

在DefaultAdvisorAdapterRegistry的构造方法中,当它被创建的时候就会初始化出三个AdvisorAdapter,分别是MethodBeforeAdviceAdapter,AfterReturningAdviceAdapter,AfterReturningAdviceAdapter,所以DefaultAdvisorAdapterRegistry这个类就是包装了AdvisorAdapter,也符合了这个类的类名的含义,我们这里以MethodBeforeAdviceAdapter为例看看里面到底做了什么

class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {

   //判断该AdvisorAdapter能够适配哪一种advice
   //MethodBeforeAdviceAdapter这个类型的AdvisorAdapter适配的是MethodBeforeAdvice类型的advice
   @Override
   public boolean supportsAdvice(Advice advice) {
      return (advice instanceof MethodBeforeAdvice);
   }

   //把advice增强器装换成对应的MethodInterceptor
   //MethodBeforeAdvice这个类型的增强器对应转换成MethodBeforeAdviceInterceptor
   @Override
   public MethodInterceptor getInterceptor(Advisor advisor) {
      MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
      return new MethodBeforeAdviceInterceptor(advice);
   }

}

所以通过对MethodBeforeAdviceAdapter这个类型的AdvisorAdapter的代码来看,我们就知道AdvisorAdapter就是用来适配指定的advice的,而每一种advice都有对应的MethodInterceptor进行包装,如下图可以看出advice的类继承关系以及每种advice所对应具体的MethodInteceptor

?getInterceptorsAndDynamicInterceptionAdvice小总结:这个方法比较重要,它是DefaultAdvisorChainFactory这个类里面的一个方法,AdvisorChainFactory顾名思义就是根据advisor得到拦截器链的工厂的意思,所以上面的分析我们可以得知这个方法主要做的就是从适用于目标类的所有advisor中找到能够拦截当前目标执行方法的advisor,然后把这些advisor交由AdvisorAdapter去装换成对应的MethodInterceptor,从而最终得到一个能够拦截目标执行方法的MethodInterceptor数组,也就是我们所说的方法拦截链

org.springframework.aop.framework.ReflectiveMethodInvocation#proceed

public Object proceed() throws Throwable {
   // We start with an index of -1 and increment early.
   //这里主要是判断是否已经执行完了所有的拦截器
   //如果是的话,就执行invokeJoinpoint方法,这个方法里面做的就是执行代理对象的目标方法
   if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
      return invokeJoinpoint();
   }

    //按顺序从0开始从拦截器链中获取拦截器
   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.
      //直接执行拦截器的invoke方法,并且把当前的RefectiveMethodInvocation对象作为参数传进去
      return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
   }
}

上面重点的就是拦截器的invoke方法执行了,我们这里可以思考,这里也没有使用循坏,拦截器有多个的话spring是如何做到执行完一个又执行下一个的呢?答案就在这个invoke方法中了,在invoke方法中,由于把当前的RefectiveMethodInvocation对象作为了参数传了进去,所以在invoke方法中就能够继续调用RefectiveMethodInvocation的proceed方法,其实就相当于一个递归去进行调用

假设现在有两个MethodInteceptor,一个是MethodBeforeAdviceInteceptor,另一个是AfterReturningAdviceInteceptor,当执行MethodBeforeAdviceInteceptor的invoke方法的时候

@Override
public Object invoke(MethodInvocation mi) throws Throwable {
    //会执行AspectJMethodBeforeAdvice的before方法,也就是我们在aspect切面中定义的@before方法
   this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
   //当执行完@before方法之后会继续调用RefectiveMethodInvocation的proceed方法
   //此时会来到AfterReturningAdviceInteceptor的invoke方法
   return mi.proceed();
}

接下来执行AfterReturningAdviceInteceptor的invoke方法

@Override
public Object invoke(MethodInvocation mi) throws Throwable {
    //再去执行RefectiveMethodInvocation的proceed方法
    //此时进入proceed方法一开始的if判断就会成立,执行代理对象的目标方法
   Object retVal = mi.proceed();
   //proceed方法执行完之后就去执行AspectJAfterReturningAdvice的afterReturning方法
   this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
   return retVal;
}

以上就是SpringAOP底层API的一个代理对象的方法执行流程,具体拦截器对应的各种advice增强器我们之后再详细讨论里面的细节实现。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-07-16 21:56:32  更:2021-07-16 21:56:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/7 17:04:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码