项目启动时,创建代理过程
initializeBean.applyBeanPostProcessorsAfterInitialization
由AnnotationAwareAspectJAutoProxyCreator来处理
AnnotationAwareAspectJAutoProxyCreator
wrapIfNecessary
- 通过getAdvicesAndAdvisorsForBean获取bean满足的Advisor,这里只有返回了事务相关的Advisor
- this.advisedBeans.put(cacheKey, Boolean.TRUE);放入缓存
- 开始创建代理createProxy
createProxy
创建动态代理,通过jdk或者cglib,这个在前面spring的分析由讲到,略
生成的cglib文件,下面是我们要测试的dynamicUpdate方法
执行MethodInterceptor的intercept方法,这里的MethodInterceptor是CglibAopProxy.DynamicAdvisedInterceptor
4. this.proxyTypes.put(cacheKey, proxy.getClass());缓存bean->代理Class
执行时,AOP处理
CglibAopProxy.DynamicAdvisedInterceptor执行intercept
这是通用的AOP执行过程
General purpose AOP callback. Used when the target is dynamic or when the proxy is not frozen.
最后执行MethodInterceptor的invoke回调。这里由TransactionInterceptor实现
TransactionInterceptor事务拦截器
invokeWithinTransaction
- 341行,获取注解上参数
- 342行,获取事务控制器TM。默认为JdbcTransactionManager
- 382行,创建事务对象
createTransactionIfNecessary创建TransactionInfo对象
status = tm.getTransaction(txAttr); 获取事务状态
doGetTransaction 获取事务对象
ConnectionHolder conHolder =(ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());
- 通过obtainDataSource()获取dataSource
这里的dataSource是DynamicDataSource,这是我自定义的Datasource,用来做读写分离的
public class DynamicDataSource extends AbstractRoutingDataSource {
private Object writeDataSource;
private Object readDataSource;
@Override
public void afterPropertiesSet() {
if (this.writeDataSource == null) {
throw new IllegalArgumentException("Property 'writeDataSource' is required");
}
setDefaultTargetDataSource(writeDataSource);
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put(DynamicDataSourceGlobalEnum.WRITE.name(), writeDataSource);
if (readDataSource != null) {
targetDataSources.put(DynamicDataSourceGlobalEnum.READ.name(), readDataSource);
}
setTargetDataSources(targetDataSources);
super.afterPropertiesSet();
}
@Override
protected Object determineCurrentLookupKey() {
// 开启事务,用主数据源
return DynamicDataSourceHolder.getDataSource() == DynamicDataSourceGlobalEnum.WRITE ? DynamicDataSourceGlobalEnum.WRITE.name() : DynamicDataSourceGlobalEnum.READ.name();
}
}
2. TransactionSynchronizationManager.getResource
3. 返回事务对象
isExistingTransaction判断当前是否存在事务
startTransaction开启事务
doBegin
1. 获取数据库连接
2. 将数据库连接封装成ConnectionHolder,并设置到事务对象的connectionHolder字段中,最后返回连接对象
3. 设置只读事务标识
4. 查询数据库当前连接是否为自动提交,如果是自动提交设置为手动
5. 如果为只读事务
Statement执行executeUpdate(“SET TRANSACTION READ ONLY”);
6. 设置事务超时时间,默认为不超时(-1)
7. 绑定ConnectionHolder到当前线程
prepareSynchronization 初始化当前线程事务参数
所有属性都绑定到当前线程
prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
把TransactionInfo绑定到当前线程
invocation.proceedWithInvocation(); 执行业务代码
cleanupTransactionInfo(txInfo);
在业务代码执行完成后,在finally中
commitTransactionAfterReturning 提交事务
最终调用Connection.commit提交事务
processReturnType(proxy, target, method, retVal);
执行通用AOP后置通知