zoukankan      html  css  js  c++  java
  • 调试:Spring AOP执行过程

    调试项目:https://github.com/1367356/laboratoryWeb

    断点位置

    点击查询:http://localhost:9002/queryNews?htmlid=1531872732684

    1:  controler拦截,进入调试点。

    News news=foreService.queryNews(htmlid);  //查询新闻

    2:  进入service层打log

    logger.debug(htmlid);

    3:  打log,  省略后面n步....

        public void debug(final Object message) {
            logIfEnabled(FQCN, Level.DEBUG, null, message, null);
        }

    4:service层 查询新闻。这是已经生成了Mapper代理对象 MapperProxy

    return foreMapper.queryNews(htmlid);

    5:进入JDK动态代理,执行代理方法,proxy是Mapper代理对象 :final class JdkDynamicAopProxy 

    进入代理方法之前生成了已经生成了ForeMapper代理类,代理类包含SqlSession信息,Mapper.xml中的sql信息。

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            MethodInvocation invocation;
            Object oldProxy = null;
            boolean setProxyContext = false;
    
            TargetSource targetSource = this.advised.targetSource;
            Class<?> targetClass = null;
            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;
                }
    
                // May be null. Get as late as possible to minimize the time we "own" the target,
                // in case it comes from a pool.
                target = targetSource.getTarget();
                if (target != null) {
                    targetClass = target.getClass();  //执行,获取目标类
                }
    
                // 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  ,检查是否有 通知advice  aop:aftere等(拦截链),也就是说该方法是否被拦截。
                // 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);
                }
            }
        }

    6:使用target,生成一个代理类 targetClass.  生成的是字节码对象。

     7:  获取方法的拦截链

    https://blog.csdn.net/xiejx618/article/details/43820417

    List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

    8:    因为拦截连不为空执行下面的。生成反射方法调用对象,是生成一个含有调用方法的对象,不是生成包含ForeMapper中所有方法的对象。

                    invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);  //生成包含 反射方法 的对象,如下
                    // Proceed to the joinpoint through the interceptor chain.  //执行切入点
                    retVal = invocation.proceed();

    生成的invocation对象,代理了ForeMapper中一个方法(queryNews)的代理对象。

    9:执行代理方法

    retVal = invocation.proceed();

      进入:public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable 

        @Override
        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;
                if (dm.methodMatcher.matches(this.method, this.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);   //执行
            }
        }

     10:进入:public class PersistenceExceptionTranslationInterceptor

          implements MethodInterceptor, BeanFactoryAware, InitializingBean {
        @Override
        public Object invoke(MethodInvocation mi) throws Throwable {
            try {
                return mi.proceed();  //执行
            }
            catch (RuntimeException ex) {
                // Let it throw raw if the type of the exception is on the throws clause of the method.
                if (!this.alwaysTranslate && ReflectionUtils.declaresException(mi.getMethod(), ex.getClass())) {
                    throw ex;
                }
                else {
                    if (this.persistenceExceptionTranslator == null) {
                        this.persistenceExceptionTranslator = detectPersistenceExceptionTranslators(this.beanFactory);
                    }
                    throw DataAccessUtils.translateIfNecessary(ex, this.persistenceExceptionTranslator);
                }
            }
        }

    11:进入 public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable 

     执行:

        @Override
        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;
                if (dm.methodMatcher.matches(this.method, this.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);
            }
        }

    执行:

        protected Object invokeJoinpoint() throws Throwable {
            return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
        }

    12 进入: * @see org.springframework.aop.framework.AopProxyUtils

             public abstract class AopUtils   执行下面
        public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args)
                throws Throwable {
    
            // Use reflection to invoke the method.  //使用反射调用方法
            try {
                ReflectionUtils.makeAccessible(method);  //对方法进行验证13步
                return method.invoke(target, args);      //调用方法14步
            }
            catch (InvocationTargetException ex) {
                // Invoked method threw a checked exception.
                // We must rethrow it. The client won't see the interceptor.
                throw ex.getTargetException();
            }
            catch (IllegalArgumentException ex) {
                throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
                        method + "] on target [" + target + "]", ex);
            }
            catch (IllegalAccessException ex) {
                throw new AopInvocationException("Could not access method [" + method + "]", ex);
            }
        }

    13:进入:public abstract class ReflectionUtils   对方法进行验证

        public static void makeAccessible(Method method) {
            if ((!Modifier.isPublic(method.getModifiers()) ||
                    !Modifier.isPublic(method.getDeclaringClass().getModifiers())) && !method.isAccessible()) {
                method.setAccessible(true);
            }
        }

    14: 调用方法,

    return method.invoke(target, args);

    15:进入Mapper代理:public class MapperProxy<T> implements InvocationHandler, Serializable 

     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        try {
          if (Object.class.equals(method.getDeclaringClass())) {
            return method.invoke(this, args);
          } else if (isDefaultMethod(method)) {
            return invokeDefaultMethod(proxy, method, args);
          }
        } catch (Throwable t) {
          throw ExceptionUtil.unwrapThrowable(t);
        }
        final MapperMethod mapperMethod = cachedMapperMethod(method);  //执行
        return mapperMethod.execute(sqlSession, args);
      }

    16:生成MapperMethod对象,  这是一个只包含调用方法的代理对象。当调用时,会在代理对象中执行SqlSession信息(Sql语句)。

      private MapperMethod cachedMapperMethod(Method method) {
        MapperMethod mapperMethod = methodCache.get(method);
        if (mapperMethod == null) {
          mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());
          methodCache.put(method, mapperMethod);
        }
        return mapperMethod;
      }

    17: 进入SqlSessionTemplate : public class SqlSessionTemplate implements SqlSession, DisposableBean ,执行

      public Configuration getConfiguration() {
        return this.sqlSessionFactory.getConfiguration();
      }

    18:进入DefaultSqlSessionFactory :public class DefaultSqlSessionFactory implements SqlSessionFactory  执行:

      public Configuration getConfiguration() {
        return configuration;
      }

    configuration包含Mapper中的各个Sql信息。

     19:SqlSessionTemplate 返回包含configuration的sqlSessionFactory

      @Override
      public Configuration getConfiguration() {
        return this.sqlSessionFactory.getConfiguration();
      }

     20:  进入:public class MapperMethod 

    用configuration配置  MapperMethod,生成MapperMethod对象。

      public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {
        this.command = new SqlCommand(config, mapperInterface, method);
        this.method = new MethodSignature(config, mapperInterface, method);
      }

    21:SqlCommand  方法生成Sql命令,将configuration中的sql信息取出。Sql命令是MapperMethod对象的一部分。

        public SqlCommand(Configuration configuration, Class<?> mapperInterface, Method method) {
          final String methodName = method.getName();
          final Class<?> declaringClass = method.getDeclaringClass();
          MappedStatement ms = resolveMappedStatement(mapperInterface, methodName, declaringClass,
              configuration);     //生成的sql Statement
          if (ms == null) {
            if (method.getAnnotation(Flush.class) != null) {
              name = null;
              type = SqlCommandType.FLUSH;
            } else {
              throw new BindingException("Invalid bound statement (not found): "
                  + mapperInterface.getName() + "." + methodName);
            }
          } else {
            name = ms.getId();
            type = ms.getSqlCommandType();
            if (type == SqlCommandType.UNKNOWN) {
              throw new BindingException("Unknown execution method for: " + name);
            }
          }
        }

    22:执行method

    23:进入MapperMethod :执行

      public Object execute(SqlSession sqlSession, Object[] args) {
        Object result;
        switch (command.getType()) {
          case INSERT: {
            Object param = method.convertArgsToSqlCommandParam(args);
            result = rowCountResult(sqlSession.insert(command.getName(), param));
            break;
          }
          case UPDATE: {
            Object param = method.convertArgsToSqlCommandParam(args);
            result = rowCountResult(sqlSession.update(command.getName(), param));
            break;
          }
          case DELETE: {
            Object param = method.convertArgsToSqlCommandParam(args);
            result = rowCountResult(sqlSession.delete(command.getName(), param));
            break;
          }
          case SELECT:
            if (method.returnsVoid() && method.hasResultHandler()) {
              executeWithResultHandler(sqlSession, args);
              result = null;
            } else if (method.returnsMany()) {
              result = executeForMany(sqlSession, args);
            } else if (method.returnsMap()) {
              result = executeForMap(sqlSession, args);
            } else if (method.returnsCursor()) {
              result = executeForCursor(sqlSession, args);
            } else {
              Object param = method.convertArgsToSqlCommandParam(args);   //执行
              result = sqlSession.selectOne(command.getName(), param);
            }
            break;
          case FLUSH:
            result = sqlSession.flushStatements();
            break;
          default:
            throw new BindingException("Unknown execution method for: " + command.getName());
        }
        if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
          throw new BindingException("Mapper method '" + command.getName() 
              + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
        }
        return result;
      }

    24: 得到参数param=... ,commond.getName=queryNews()

    25:  通过sqlSession执行方法,返回结果。

    26:返回结果,成功。

     Spring Aop简单实现:https://github.com/1367356/GradleTestUseSubModule/tree/master/SpringAOPTheory

    Spring AOP的执行流程:https://blog.csdn.net/qq418517226/article/details/51284298

  • 相关阅读:
    AtCoder ABC 129F Takahashi's Basics in Education and Learning
    AtCoder ABC 129E Sum Equals Xor
    UVA 511 Do You Know the Way to San Jose?
    UVA 12504 Updating a Dictionary
    [Poi2000] 病毒
    [loj10061] 最短母串
    [Poi2010] Antisymmetry
    校内集训20181003
    校内集训20181001
    校内集训20180925
  • 原文地址:https://www.cnblogs.com/liyafei/p/9330069.html
Copyright © 2011-2022 走看看