<tx:annotation-driven .../>
使用的是aop机制:
”advisor“、”拦截器“、”注解解析器“
<tx:annotation-driven transaction-manager="transactionManagerx" mode="proxy" /> 启动aop的功能,并注册aop的自定义Advisor对象到BeanDefinition容器
{
1、注册 TransactionalEventListenerFactory 到 registry
2、注册 hook
1、配置 mode="proxy"
1、注册 InfrastructureAdvisorAutoProxyCreator 到 registry 【BeanPostProcessor】
如果有设置 proxy-target-class="",那么设置InfrastructureAdvisorAutoProxyCreator的属性
definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
如果有设置 expose-proxy="",那么设置InfrastructureAdvisorAutoProxyCreator的属性
definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
2、注册 AnnotationTransactionAttributeSource 到 registry
配置 AnnotationTransactionAttributeSource 的属性
sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
3、注册 TransactionInterceptor 到 registry
配置 TransactionInterceptor 的属性
interceptorDef.getPropertyValues().add("transactionManagerBeanName", TxNamespaceHandler.getTransactionManagerName(element));
interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
4、注册 BeanFactoryTransactionAttributeSourceAdvisor 到 registry
配置 BeanFactoryTransactionAttributeSourceAdvisor 的属性
advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);
advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
advisorDef.getPropertyValues().add("order", element.getAttribute("order"));
2、配置 mode="aspectj"
注册 AnnotationTransactionAspect 到 registry
配置 AnnotationTransactionAspect 的属性
def.setFactoryMethodName("aspectOf");
def.getPropertyValues().add("transactionManagerBeanName", TxNamespaceHandler.getTransactionManagerName(element));
}
// BeanPostProcessor
org.springframework.aop.aspectj.autoproxy.InfrastructureAdvisorAutoProxyCreator
{
1、实例化前
postProcessBeforeInstantiation(Class<?> beanClass, String beanName)
{
}
2、初始化后
postProcessAfterInitialization(Object bean, String beanName)
{
return wrapIfNecessary(bean, beanName, cacheKey);
{
1、过滤不能被代理的
1、 -- 实现Advice/Pointcut/Advisor/AopInfrastructureBean接口的类不能被代理
2、 -- 要创建的是“接受通知的对象”,那么就要跳过了,不然陷入死循环
2、getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null) --- 获取符合条件的“通知接受者”列表
findEligibleAdvisors(Class<?> beanClass, String beanName)
{
1、findCandidateAdvisors()
{
for(迭代所有实现Advisor接口的bean)
{
1、isEligibleBean(name)
{
isEligibleAspectBean(beanName)
{
1、BeanDefinition的Role为ROLE_INFRASTRUCTURE
}
}
}
}
2、findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName) --- 匹配“通知接受者”列表
{
1、ClassFilter匹配
2、MethodMatcher匹配 - 《类中只要有一个方法能命中,就符合》
}
3、sortAdvisors(eligibleAdvisors) --- 对结果进行排序
}
3、创建代理对象 - 返回
1、配置优化模式
new ObjenesisCglibAopProxy(config);
2、没配置优化模式
new JdkDynamicAopProxy(config)
}
}
}
// "通知接收者"
org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor
{
transactionAttributeSource : AnnotationTransactionAttributeSource, // 用于识别注解
adviceBeanName : 对应拦截器
}
// 注解识别
org.springframework.transaction.annotation.AnnotationTransactionAttributeSource
{
// 注解 org.springframework.transaction.annotation.Transactional
// 注解 javax.transaction.Transactional
// 注解 javax.ejb.TransactionAttribute
getTransactionAttribute(Method method, Class<?> targetClass) --- 获取事务属性
{
1、默认值识别public类型的方法(可配置)
2、如果cglib生成的,那么定位到用户定义的实际类
3、在“实现类的方法”上检查@Transactional注解信息,如果找到直接return
4、在“实现类”上检查@Transactional注解信息,如果找到直接return
5、在“接口类的方法”上检查@Transactional注解信息,如果找到直接return
6、在“接口类”上检查@Transactional注解信息,如果找到直接return
}
}
// 拦截器
org.springframework.transaction.interceptor.TransactionInterceptor
{
invoke(final MethodInvocation invocation)
{
1、获取方法或者类上@Transactional配置的事务属性
2、根据事务属性获取事务管理器
3、执行事务
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification); // 创建事务,如果需要。org.springframework.transaction.interceptor.TransactionAspectSupport.TransactionInfo
{
status = tm.getTransaction(txAttr); // 获取事务状态
{
DefaultTransactionStatus status = newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); // 创建事务状态器
doBegin(transaction, definition); // 开启事务,禁止事务自动提交,把连接放入线程上下文
}
return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status); -- 用TransactionInfo包装TransactionStatus
{
TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);
txInfo.bindToThread(); // 把TransactionInfo绑定到当前线程上下文
return txInfo;
}
}
Object retVal = null;
try {
retVal = invocation.proceedWithInvocation(); // 执行目标方法
}
catch (Throwable ex) {
completeTransactionAfterThrowing(txInfo, ex); // 根据异常配置进行“回滚、或者提交”
throw ex;
}
finally {
cleanupTransactionInfo(txInfo);
}
commitTransactionAfterReturning(txInfo); // 提交事务
return retVal;
}
}
配置拦截器
<tx:advice id="advice0" transaction-manager="transactionManagerx">
<tx:attributes>
<!-- MineRuntimeException的子类异常都回滚,除了MineSubOneRuntimeException异常的不回滚 -->
<tx:method name="testException*" rollback-for="cn.java.demo.txtag.real.exception.MineRuntimeException,cn.java.demo.txtag.real.exception.MineRuntimeException"
no-rollback-for="cn.java.demo.txtag.real.exception.MineSubOneRuntimeException,cn.java.demo.txtag.real.exception.MineSubOneRuntimeException"/> <!-- rollback-for和no-rollback-for,会依次匹配父类名的特征,谁最接近本类谁优先级较高 -->
<tx:method name="find*" propagation="NOT_SUPPORTED" isolation="REPEATABLE_READ" timeout="-1" read-only="true" /> <!-- propagation="NOT_SUPPORTED" 如果支持事务就使用事务执行,如果不支持事务就使用非事务执行 -->
<tx:method name="insert*" propagation="REQUIRED" isolation="REPEATABLE_READ" timeout="10" read-only="false" /> <!-- propagation="REQUIRED" 如果存在事务就使用,如果不存在就创建 -->
<tx:method name="delete*" propagation="REQUIRED" isolation="REPEATABLE_READ" timeout="-1" read-only="false" />
<tx:method name="update*" propagation="REQUIRED" isolation="REPEATABLE_READ" timeout="-1" read-only="false" />
</tx:attributes>
</tx:advice>
注册 TransactionInterceptor 到 registry
配置 TransactionInterceptor 的属性
interceptorDef.getPropertyValues().add("transactionManagerBeanName", TxNamespaceHandler.getTransactionManagerName(element));
interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));