调试项目: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

调试:Spring AOP执行过程的更多相关文章

  1. spring aop 执行顺序

    aop 执行顺序: // @Before // @AfterThrowing order 值越小,执行时越靠前 // @After // @AfterReturning order 值越大,执行时越靠 ...

  2. Spring事务执行过程

    先说一下启动过程中的几个点: 加载配置文件: AbstractAutowireCapableBeanFactory.doCreateBean --> initializeBean --> ...

  3. Spring AOP执行方法

      execution(* springinaction.springidol.Instrument.play(..)) * 代表返回为任意类型 springinaction.springidol.I ...

  4. (4.1)Spring MVC执行原理和基于Java的配置过程

    一.Spring MVC执行原理和基于Java配置的配置过程 (一)Spring MVC执行过程,大致为7步. 所有的请求都会经过Spring的一个单例的DispacherServlet. Dispa ...

  5. Spring MVC执行原理和基于Java的配置过程

    一.Spring MVC执行原理和基于Java配置的配置过程 (一)Spring MVC执行过程,大致为7步. 所有的请求都会经过Spring的一个单例的DispacherServlet. Dispa ...

  6. 按照自己的思路去研究Spring AOP源码【1】

    目录 一个例子 Spring AOP 原理 从@EnableAspectJAutoProxy注解入手 什么时候会创建代理对象? 方法执行时怎么实现拦截的? 总结 问题 参考 一个例子 // 定义一个切 ...

  7. 【Spring Framework】Spring入门教程(六)Spring AOP使用

    Spring的AOP 动态代理模式的缺陷是: 实现类必须要实现接口 -JDK动态代理 无法通过规则制定拦截无需功能增强的方法. Spring-AOP主要弥补了第二个不足,通过规则设置来拦截方法,并对方 ...

  8. Spring课程 Spring入门篇 6-1 Spring AOP API的PointCut、advice的概念及应用

    本节主要是模拟spring aop 的过程. 实现spring aop的过程 这一节老师虽然说是以后在工作中不常用这些api,实际上了解还是有好处的, 我们可以从中模拟一下spring aop的过程. ...

  9. Spring AOP 源码分析 - 拦截器链的执行过程

    1.简介 本篇文章是 AOP 源码分析系列文章的最后一篇文章,在前面的两篇文章中,我分别介绍了 Spring AOP 是如何为目标 bean 筛选合适的通知器,以及如何创建代理对象的过程.现在我们的得 ...

随机推荐

  1. Buff系统

    BUFF状态可以通过游戏道具.使用技能.被攻击技能.NPC.宠物等等实现.BUFF状态,有很多技能在释放后,会对目标产生一定时间的额外影响,这些影响有的是增益的,有的是减免的.比如法师的“熔岩地”,会 ...

  2. Unity3D协程

    协程介绍 Unity的协程系统是基于C#的一个简单而强大的接口 ,IEnumerator,它允许你为自己的集合类型编写枚举器.这一点你不必关注太多,我们直接进入一个简单的例子来看看协程到底能干什么.首 ...

  3. MathType使用中的四个小技巧

    MathType是一种比较常见的数学公式编辑器,常常与office搭配着使用,我们在使用的时候有一些要注意的小技巧,下面我们就来给大家介绍介绍MathType使用中的四个小技巧? 技巧一:调整工具栏显 ...

  4. mysql中,now()函数和sysdate()函数有什么区别?

    问题描述: 今天在看mysql的时间函数,now()和sysdate(),记录下两者之间有什么不同. 实验过程: 1.执行以下的两个语句: mysql),now(); +--------------- ...

  5. Android NDK开发-2-环境搭建

    1.环境变量配置NDK 2.选中项目,右键属性菜单,创建一个新的编译器

  6. docker学习-docker安装

    win10之外的系统:https://www.docker.com/products/docker-toolbox win10系统:        https://www.docker.com/pro ...

  7. C++异常 返回错误码

    一种比异常终止更灵活的方法是,使用函数的返回值来指出问题.例如,ostream类的get(void)成员ASCII码,但到达文件尾时,将返回特殊值EOF.对hmean()来说,这种方法不管用.任何树脂 ...

  8. 原来 CSS 与 JS 是这样阻塞 DOM 解析和渲染的

    hello~各位亲爱的看官老爷们大家好.估计大家都听过,尽量将CSS放头部,JS放底部,这样可以提高页面的性能.然而,为什么呢?大家有考虑过么?很长一段时间,我都是知其然而不知其所以然,强行背下来应付 ...

  9. ajax的历史

    ajax (AJAX开发) 编辑 AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术. AJAX ...

  10. 关于hql语句的一些问题

    1.student is not mapped问题: 在执行显示数据库数据的时候出错 大概提示说: errors: s.entr_Id student is not mapped 碰到这种情况一般是: ...