spring中aop源码分析(四)

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】

spring中aop源码分析(四)

我们直接看JdkDynamicAopProxy的invoke方法 由于JdkDynamicAopProxy实现了InvocationHandler

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       MethodInvocation invocation;
       Object oldProxy = null;
       boolean setProxyContext = false;
       //获取目标对象
       TargetSource targetSource = this.advised.targetSource;
       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...
             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);
          }
       }
    }

我们看下获取拦截器

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

       //这里获取那个类上面的advisor长度
       List<Object> interceptorList = new ArrayList<>(config.getAdvisors().length);
       Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
       boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
       AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

       for (Advisor advisor : config.getAdvisors()) {
          if (advisor instanceof PointcutAdvisor) {
             // Add it conditionally.
             PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
             if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
                //将advisor转变为MethodInterceptor数组对象
                MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
                   if (mm.isRuntime()) {

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

下面我接着往下看:

首先我们要知道我们这个registry对象是

    DefaultAdvisorAdapterRegistry

在它的构造方法里面我们看到如下代码

    public DefaultAdvisorAdapterRegistry() {
       registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
       registerAdvisorAdapter(new AfterReturningAdviceAdapter());
       registerAdvisorAdapter(new ThrowsAdviceAdapter());
    }

在这里注册了三个适配器分别是方法前置/方法返回/异常处理然后我看是如何将advisor转变为MethodInterceptor[]数组对象

    public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
       List<MethodInterceptor> interceptors = new ArrayList<>(3);
       Advice advice = advisor.getAdvice();
       if (advice instanceof MethodInterceptor) {
          interceptors.add((MethodInterceptor) advice);
       }
       for (AdvisorAdapter adapter : this.adapters) {
        //这里判断适配器是否使用这个advice
          if (adapter.supportsAdvice(advice)) {
              //如果使用则进行转换
             interceptors.add(adapter.getInterceptor(advisor));
          }
       }
       if (interceptors.isEmpty()) {
          throw new UnknownAdviceTypeException(advisor.getAdvice());
       }
       return interceptors.toArray(new MethodInterceptor[0]);
    }

我们进入到异常Advice适配器中,发现它这里就是判断advice是ThrowsAdvice吗

    @Override
    public boolean supportsAdvice(Advice advice) {
       return (advice instanceof ThrowsAdvice);
    }
    public MethodInterceptor getInterceptor(Advisor advisor) {
       return new ThrowsAdviceInterceptor(advisor.getAdvice());
    }

然在构造成ThrowAdviceInterceptor对象 而ThrowAdviceInterceptor实现了MethodInterceptor方法 我们看下的invoke方法

    public Object invoke(MethodInvocation mi) throws Throwable {
       try {
         //处理目标方法
          return mi.proceed();
       }
       catch (Throwable ex) {
          Method handlerMethod = getExceptionHandler(ex);
          if (handlerMethod != null) {
             //出现异常才执行下面方法
             invokeHandlerMethod(mi, ex, handlerMethod);
          }
          throw ex;
       }
    }
    private void invokeHandlerMethod(MethodInvocation mi, Throwable ex, Method method) throws Throwable {
       Object[] handlerArgs;
       if (method.getParameterCount() == 1) {
          handlerArgs = new Object[] { ex };
       }
       else {
          handlerArgs = new Object[] {mi.getMethod(), mi.getArguments(), mi.getThis(), ex};
       }
       try {
          method.invoke(this.throwsAdvice, handlerArgs);
       }
       catch (InvocationTargetException targetEx) {
          throw targetEx.getTargetException();
       }
    }

来源:[]()

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » spring中aop源码分析(四)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏