源码解读全文
初始化流程
EnableTransactionManagement注解
- 将
ProxyTransactionManagementConfiguration
注册,其中分别注册了三个Bean
- 实际名字为
"org.springframework.transaction.config.internalTransactionAdvisor";
,作为切面类,包括transactionAttributeSource
和transactionInterceptor
封装了事务的切点以及相关属性
transactionAttributeSource
切点属性资源transactionInterceptor
切面方法执行器- 由此可以看出,事务是直接将切面方法注册进容器,并没有通过
AOP
扫描所有Bean
,获取切面资源
重要的类
PlatformTransactionManager
,模板接口,规定了commit/rollback/getTransaction
方法
生成代理对象流程
- 初始化
Bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
- 调用初始化后的后置处理
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
- 调用
AbstractAutoProxyCreator
的postProcessAfterInitialization
,其中调用wrapIfNecessary(bean, beanName, cacheKey);
- 获取可以运用到该类上的切面执行器
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
此时
specificInterceptors
为internalTransactionAdvisor
切面类
- 创建代理对象
Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
将信息封装给
proxyFactory
,根据是否实现接口cglib/jdk
创建代理
getAdvicesAndAdvisorsForBean获取该类的切面执行器
- 找到所有切面
List<Advisor> candidateAdvisors = findCandidateAdvisors();
获取所有
cachedAdvisorBeanNames
,通过getBean
添加到advisors
- 根据该类进行筛选
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
- 筛选
AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
- 遍历所有切面
- 如果是
PointcutAdvisor
的类型,调用canApply(pca.getPointcut(), targetClass, hasIntroductions);
PointcutAdvisor.canApply切面匹配
- 获取该类及其接口的实现类
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
methodMatcher.matches(method, targetClass)
- 获取所有事务切点属性资源
TransactionAttributeSource tas = getTransactionAttributeSource();
- 尝试获取当前方法的事务信息,如果没有,为其创建
TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
,解析@Transactional
注解
- 当比较到
internalTransactionAdvisor
,methodMatcher
实际上为TransactionAttributeSourcePointcut
,是事务的类 - 通过事务中的
transactionAttributeSource
,进行解析@Transactional
注解,并进行缓存
调用流程
- 从切面中获取执行链
1.将该方法的切面转换为执行器
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
2. 通过获取切面类的增强器Advice advice = advisor.getAdvice();
,并转换成执行器interceptors.add((MethodInterceptor) advice);
3. 保存在this.methodCache.put(cacheKey, cached);
4. 此时获得的是transactionInterceptor
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
- 封装成
CglibMethodInvocation
方法执行器,链式调用
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
- 调用
TransactionInterceptor.invoke
invokeWithinTransaction
- 创建事务信息
TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
- 执行目标方法
retVal = invocation.proceedWithInvocation();
,此时回到执行链执行流程,此时执行链已完成,执行目标方法,执行完成后,执行提交/回滚
createTransactionIfNecessary
- 开始事务
startTransaction(def, transaction, debugEnabled, suspendedResources);
- 正式开始
DataSourceTransactionManager
的doBegin(transaction, definition);
- 检查是否有数据库连接
txObject.hasConnectionHolder()
,没有则创建
- 创建连接
Connection newCon = obtainDataSource().getConnection();
- 设置给
ConnectionHolder
,txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
- 设置事务为
false
,con.setAutoCommit(false);
- 如果
txObject.isNewConnectionHolder()
,将这个连接绑定给线程TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
- 将当前数据源的连接,绑定给线程,
ThreadLocal
数据库执行过程
- 获取链接
ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
从
resource
中
- 执行过程中,需要获取连接
jdbcTemplate.execute("update bank set money = money + 100 where name = 'zhangsan';");
- 传入的是一个接口匿名实现类,
doInStatement
的实现,sql
为语句