调试项目: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层 查询新闻。
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); //调用Joinpoint } 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:
Spring AOP的执行流程:https://blog.csdn.net/qq418517226/article/details/51284298