調試項目: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