调试项目: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. Java任务调度开源框架quartz学习

    一.quartz学习 Java框架介绍:Quartz从入门到进阶 http://edu.yesky.com/edupxpt/233/2209233.shtml 1.例子:http://javacraz ...

  2. centos7 systemctl

    下机为systemctl指令systemctl enable *.service #开机运行服务systemctl disable *.service #取消开机运行systemctl start * ...

  3. oracle_存储过程_没有参数_更新过期申请单以及写日志事务回滚

    CREATE OR REPLACE PROCEDURE A_MEAS_MIINSP_PLAN_UPDATEASvs_msg VARCHAR2(4000);log_body VARCHAR2(400); ...

  4. MySQL技术内幕:SQL编程 第2章 数据类型 读书笔记

    2.1 类型属性 2.1.1 UNSIGNED 数字无符号化, INT的值 -2147483648 ~ 2147483647  INT UNSIGNED的值 0 ~ 4294967295 int a ...

  5. python2.0_s12_day13_javascript&Dom&jQuery

    今天主要内容:JavaScriptDomjQuery http://www.cnblogs.com/wupeiqi/articles/5369773.html 今天主要内容大致了解:javascrip ...

  6. 数组内Merge

    数组al[0...mid-1]和al[mid...num-1]两个部分都已经分别排好序.要求合并使得整个数组al有序.请给出合并merge的代码.要求空间复杂度为O(1). /* 数组a[begin, ...

  7. 《C++ Primer Plus》15.4 RTTI 学习笔记

    运行时类型识别RTTI(Runtime Type Identification) C++有三个支持RTTI的元素.* 如果可能的话,dynamic_cast运算符将使用一个指向基类的指针来生成一个指向 ...

  8. iOS-代码修改Info.plist文件

    解决办法: 1.首先系统的Info.Plist文件是只读文件 并不能 写入.目前我个人是没有办法存入,官方属性 可以看到是readOnly 2.那么我们 就想代码修改Info.Plist文件怎么办呢, ...

  9. c++11——lambda表达式

    lambda表达式 函数式编程的一个语法,有如下优点: (1)声明式编程风格:就地匿名定义目标函数或函数对象,不需要额外写一个命名函数或者函数对象.以更直接的方式写程序,好的可读性和可维护性. (2) ...

  10. 【Mysql】 case ... when ... 用法

    sql语句查询时给某个空字段赋值 SELECT CASE WHEN field= '' THEN ' WHEN fieldIS NULL THEN ' ELSE field END FROM tabl ...