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

调试:Spring AOP执行过程的更多相关文章
- spring aop 执行顺序
aop 执行顺序: // @Before // @AfterThrowing order 值越小,执行时越靠前 // @After // @AfterReturning order 值越大,执行时越靠 ...
- Spring事务执行过程
先说一下启动过程中的几个点: 加载配置文件: AbstractAutowireCapableBeanFactory.doCreateBean --> initializeBean --> ...
- Spring AOP执行方法
execution(* springinaction.springidol.Instrument.play(..)) * 代表返回为任意类型 springinaction.springidol.I ...
- (4.1)Spring MVC执行原理和基于Java的配置过程
一.Spring MVC执行原理和基于Java配置的配置过程 (一)Spring MVC执行过程,大致为7步. 所有的请求都会经过Spring的一个单例的DispacherServlet. Dispa ...
- Spring MVC执行原理和基于Java的配置过程
一.Spring MVC执行原理和基于Java配置的配置过程 (一)Spring MVC执行过程,大致为7步. 所有的请求都会经过Spring的一个单例的DispacherServlet. Dispa ...
- 按照自己的思路去研究Spring AOP源码【1】
目录 一个例子 Spring AOP 原理 从@EnableAspectJAutoProxy注解入手 什么时候会创建代理对象? 方法执行时怎么实现拦截的? 总结 问题 参考 一个例子 // 定义一个切 ...
- 【Spring Framework】Spring入门教程(六)Spring AOP使用
Spring的AOP 动态代理模式的缺陷是: 实现类必须要实现接口 -JDK动态代理 无法通过规则制定拦截无需功能增强的方法. Spring-AOP主要弥补了第二个不足,通过规则设置来拦截方法,并对方 ...
- Spring课程 Spring入门篇 6-1 Spring AOP API的PointCut、advice的概念及应用
本节主要是模拟spring aop 的过程. 实现spring aop的过程 这一节老师虽然说是以后在工作中不常用这些api,实际上了解还是有好处的, 我们可以从中模拟一下spring aop的过程. ...
- Spring AOP 源码分析 - 拦截器链的执行过程
1.简介 本篇文章是 AOP 源码分析系列文章的最后一篇文章,在前面的两篇文章中,我分别介绍了 Spring AOP 是如何为目标 bean 筛选合适的通知器,以及如何创建代理对象的过程.现在我们的得 ...
随机推荐
- Java任务调度开源框架quartz学习
一.quartz学习 Java框架介绍:Quartz从入门到进阶 http://edu.yesky.com/edupxpt/233/2209233.shtml 1.例子:http://javacraz ...
- centos7 systemctl
下机为systemctl指令systemctl enable *.service #开机运行服务systemctl disable *.service #取消开机运行systemctl start * ...
- oracle_存储过程_没有参数_更新过期申请单以及写日志事务回滚
CREATE OR REPLACE PROCEDURE A_MEAS_MIINSP_PLAN_UPDATEASvs_msg VARCHAR2(4000);log_body VARCHAR2(400); ...
- MySQL技术内幕:SQL编程 第2章 数据类型 读书笔记
2.1 类型属性 2.1.1 UNSIGNED 数字无符号化, INT的值 -2147483648 ~ 2147483647 INT UNSIGNED的值 0 ~ 4294967295 int a ...
- python2.0_s12_day13_javascript&Dom&jQuery
今天主要内容:JavaScriptDomjQuery http://www.cnblogs.com/wupeiqi/articles/5369773.html 今天主要内容大致了解:javascrip ...
- 数组内Merge
数组al[0...mid-1]和al[mid...num-1]两个部分都已经分别排好序.要求合并使得整个数组al有序.请给出合并merge的代码.要求空间复杂度为O(1). /* 数组a[begin, ...
- 《C++ Primer Plus》15.4 RTTI 学习笔记
运行时类型识别RTTI(Runtime Type Identification) C++有三个支持RTTI的元素.* 如果可能的话,dynamic_cast运算符将使用一个指向基类的指针来生成一个指向 ...
- iOS-代码修改Info.plist文件
解决办法: 1.首先系统的Info.Plist文件是只读文件 并不能 写入.目前我个人是没有办法存入,官方属性 可以看到是readOnly 2.那么我们 就想代码修改Info.Plist文件怎么办呢, ...
- c++11——lambda表达式
lambda表达式 函数式编程的一个语法,有如下优点: (1)声明式编程风格:就地匿名定义目标函数或函数对象,不需要额外写一个命名函数或者函数对象.以更直接的方式写程序,好的可读性和可维护性. (2) ...
- 【Mysql】 case ... when ... 用法
sql语句查询时给某个空字段赋值 SELECT CASE WHEN field= '' THEN ' WHEN fieldIS NULL THEN ' ELSE field END FROM tabl ...