spring事务
Posted yanhui007
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring事务相关的知识,希望对你有一定的参考价值。
使用
ioc初始化过程注册代理类生成器,加载相关advisor到容器中
getBean时通过BeanPostProcessor回调生成代理类
通过代理类调用方法的流程
top
使用
事务的四个特性
1、原子性
2、一致性
原子性和一致性紧密联系,区别是什么?
举例:A给B转100块钱,需要两步:
1、A = A-100
2、B = B+100
原子性指把这两步放入到一个事务中,要么都执行成功,要么都失败。
一致性指的是在写代码的时候,写了1,就一定要写2,否则数据出现不一致的情况。
3、持久性:事务一旦提交,会写入到持久化存储器中,就算系统崩溃了,数据也能找回。
4、隔离性:多个事务处理相同数据的时候,他们之间应该是独立的,不能互相影响。
核心接口/类
spring本身不管理事务的具体实现,通过提供模板接口,然后持久化平台通过扩展该接口来实现事务的管理。
了解一下jdbc的事务和hibernate的事务。
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
持久化平台通过PlatformTrasactionManager的getTraction方法可以获取到事务,参数为TransactionDefination对象,TransactionDefination对象包含了事务的配置信息,这样持久化平台就知道了事务的配置信息,自己去实现事务的管理。
spring可配置事务的属性有哪些
传播行为
事务超时
回滚规则
隔离规则:定义了一个事务可以看到另一个事务中的哪些数据
是否只读
事务传播行为
spring支持7中事务传播行为,A方法调用B方法:
1、A有事务,B加入A事务,A无事务,B无事务运行
2、A有事务,B加入,A无事务,B开启新事务
3、A有事务,A事务挂起,B开启自己事务:两个事务互相独立
4、A有事务,B开启新事务,嵌套到A中:B事务失败不会影响A,A事务失败会把B也回滚。
5、A有事务,B加入,A无事务,B抛出异常
6、A有事务,挂起,B无事务运行
7、A有事务,抛异常
事务不生效的几种可能
1、数据库引擎不支持事务。
innodb支持事务,myisam不支持事务
2、事务所在的类必须被spring容器所管理
3、@Transaction注解的方法必须为public
4、自身调用
spring事务传播是指两个方法是在不同的类中,如果两个方法属于同一个类,那么事务的传播配置就会失效。
@Service
public class OrderServiceImpl implements OrderService {
@Transactional
public void update(Order order) {
this.updateOrder(order);
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateOrder(Order order) {
// update order
}
}
上面代码,updateOrder方法的事务配置是不会生效的,
原因:spring声明事务是通过spring aop实现的,spring aop会生成一个代理类,在代理类中执行事务管理逻辑,上面代码中update方法调用this.updateOrder方法不是通过代理类,所以updateOrder方法事务没有生效。
那么如何解决?
可以通过aop代理类调用updateOrder方法。
1、开启
<aop:aspectj-autoproxy expose-proxy="true"/>
2、this.updateOrder();-----------修改为--------->AopContext.currentProxy()).updateOrder();
5、异常没有正确抛出
public class OrderServiceImpl implements OrderService {
@Transactional
public void updateOrder(Order order) {
try {
// update order
} catch {
//这里没有抛出异常
}
}
}
public class OrderServiceImpl implements OrderService {
@Transactional
public void updateOrder(Order order) {
try {
// update order
} catch {//这里必须改成运行时异常
throw new Exception("更新错误");
}
}
}
隔离级别
数据库中隔离级别相关参考:https://github.com/sunyanhui123/note/issues/4#issue-399319103
spring的隔离级别有5中:
1、采用数据库设置的隔离级别
2、对应数据库的uncommited
3、commited
4、repeatable
5、串行
只读
当一个事务中有多条查询语句的时候,开启只读属性,则数据库会自动进行sql优化
回滚
默认情况下,遇到运行时异常事务会回滚,这里可以指定异常类型,还可以指定哪些异常不回滚
编程式事务
声明式事务是spring通过注解实现,提前定义好的一些。编程式事务则是在代码中自己进行事务管理,缺点是代码侵入,优点是可以自己管理事务。
声明式事务使用
推荐使用存注解方式
首先xml中配置
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation" value="classpath:hibernate.cfg.xml" />
<property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
</bean>
<!-- 定义事务管理器(声明式的事务) -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
然后在相关方法中加入注解即可
ioc初始化过程注册代理类生成器,加载相关advisor到容器中
1、spring容器在初始化过程中,遇到spring开启事务的标签tx:annotation-driven,会通过命名空间找到命名空间处理器TxNamespaceHandler,该处理器的初始化方法中给spring事务的根标签绑定了一个标签解析器AnnotationDrivenBeanDefinitionParser。
然后调用解析器的parse方法对事务标签进行解析:
2、首先注册一个代理类生成器到容器,这个生成器封装了生成代理类的方法
3、创建三种类型的bean,beanClass分别为AnnotationTransactionAttributeSource、TransactionInterceptor、BeanFactoryTransactionAttributeSourceAdvisor,他们分别封装了相应的pointcut、advice、advisor,同时将前两个bean封装到第三个bean里。
然后将这三种类型的bean都加入到spring容器中。
TxNamespaceHandler解析器的init方法:给spring事务标签绑定了标签解析器。
@Override
public void init() {
registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
}
AnnotationDrivenBeanDefinitionParser.parse:在spring ioc初始化过程中,遇到自定义标签tx:annotation-driven,执行该方法解析事务相关标签
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
registerTransactionalEventListenerFactory(parserContext);
String mode = element.getAttribute("mode");
/***
* 对于mode属性的判断
* 如果我们需要使用AspectJ的方式进行事务切入(Spring中的事务是以AOP为基础的),那么可以使用这样的配置:
* <tx:annotation-driven transaction-manager="transactionManager" mode="aspectj"/>
*/
if ("aspectj".equals(mode)) {
// mode="aspectj"
registerTransactionAspect(element, parserContext);
}
else {//正常情况进入这个分支
// mode="proxy"
AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
}
return null;
}
AnnotationDrivenBeanDefinitionParser.configureAutoProxyCreator:
该方法首先注册了代理类生成器。
然后创建三种类型的bean,beanClass分别为AnnotationTransactionAttributeSource、TransactionInterceptor、BeanFactoryTransactionAttributeSourceAdvisor,他们分别封装了相应的pointcut、advice、advisor,同时将前两个bean封装到第三个bean里。
后续获取advisor就是获取这三个bean。
public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
//注册代理类生成器
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
Object eleSource = parserContext.extractSource(element);
// 创建AnnotationTransactionAttributeSource类型的Bean,该类型bean代表pointcut
RootBeanDefinition sourceDef = new RootBeanDefinition(
"org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
sourceDef.setSource(eleSource);
sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);
// 创建TransactionInterceptor类型的Bean,该类型bean代表advice
RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
interceptorDef.setSource(eleSource);
interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registerTransactionManager(element, interceptorDef);
interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);
// 创建BeanFactoryTransactionAttributeSourceAdvisor实例bean
RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
advisorDef.setSource(eleSource);
advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
//将上面创建的AnnotationTransactionAttributeSource和TransactionInterceptor封装到BeanFactoryTransactionAttributeSourceAdvisor中
//将advice和pointcut封装到advisor中
advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);
if (element.hasAttribute("order")) {
advisorDef.getPropertyValues().add("order", element.getAttribute("order"));
}
parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);
//将上面三个Bean注册进IOC中
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));
compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));
compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));
parserContext.registerComponent(compositeDef);
}
}
getBean时通过BeanPostProcessor回调生成代理类
本章是在getBean时,通过BeanPostProcessor回调创建代理类的过程。
首先要判断是否需要创建代理类,如何判断?
该bean是否能找到匹配的advisor,如果能找到,就创建代理类。
其实就是寻找事务相关注解,匹配注解,解析注解的过程。
上面流程会将需要事务增强的方法都封装到advisor中,接下来是getBean的时候,根据BeanPostProcessor回调机制调用,根据要创建的bean去advisor中去匹配,如果匹配成功,则创建代理类。
AbstractAutoProxyCreator.postProcessAfterInitialization:
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
//几种不需要代理的情况,直接返回
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 这里是主要验证的地方,传入Bean的class与beanName去判断此Bean有哪些Advisor
//获取匹配的advisor,然后转换成拦截器链条(放入一个list中)
//入口
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// 如果有相应的advisor被找到,则用advisor与此bean做一个动态代理,将这两个的信息
// 放入代理类中进行代理
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 创建代理的地方
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
// 返回代理对象
return proxy;
}
// 如果此Bean没有一个Advisor匹配,将返回null也就是DO_NOT_PROXY
// 也就是会走到这一步,将其cacheKey,false存入Map中
this.advisedBeans.put(cacheKey, Boolean.FALSE);
// 不代理直接返回原bean
return bean;
}
AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean:获取advisor链。
@Override
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//获取所有候选advisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();//入口1
//获取可用advisor
//入口2
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
AbstractAdvisorAutoProxyCreator.findCandidateAdvisors:获取所有advisor
protected List<Advisor> findCandidateAdvisors() {
return this.advisorRetrievalHelper.findAdvisorBeans();
}
##BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans:将容器初始化阶段装进去的advisor取出来
public List<Advisor> findAdvisorBeans() {
String[] advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
if (advisorNames.length == 0) {
return new ArrayList<Advisor>();
}
List<Advisor> advisors = new ArrayList<Advisor>();
for (String name : advisorNames) {
if (isEligibleBean(name)) {
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
}
return advisors;
}
AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply:获取匹配advisor
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
// AopUtils.findAdvisorsThatCanApply:
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
//IntroductionAdvisor为引介增强
for (Advisor candidate : candidateAdvisors) {
//暂不考虑引介增强,这里一个都不会进入
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
//暂不考虑引介增强,这里一个都不会进入
continue;
}
if (canApply(candidate, clazz, hasIntroductions)) {//入口
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
public static boolean canApply(Advisor advisor, Class<?> targetClass) {
return canApply(advisor, targetClass, false);
}
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
//暂不考虑引介增强,这里一个都不会进入
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {//切点
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);//入口
}
else {//通知类型的advisor,不需要匹配,直接返回
// It doesn‘t have a pointcut so we assume it applies.
return true;
}
}
1、上面的方法中提到引介增强的概念,在此做简要说明,引介增强是一种比较特殊的增强类型,它不是在目标方法周围织入增强,而是为目标类创建新的方法和属性,所以引介增强的连接点是类级别的,而非方法级别的。通过引介增强,我们可以为目标类添加一个接口的实现,即原来目标类未实现某个接口,通过引介增强可以为目标类创建实现该接口的代理。另外这个方法用两个重载的canApply方法为目标类寻找匹配的增强器,其中第一个canApply方法会调用第二个canApply方法并将第三个参数传为false。
2、回顾一下容器初始化阶段注入到beanFactory中的三个bean:
AnnotationTransactionAttributeSource、TransactionInterceptor、BeanFactoryTransactionAttributeSourceAdvisor,
其中BeanFactoryTransactionAttributeSourceAdvisor包含另外两个。
这个BeanFactoryTransactionAttributeSourceAdvisor就是我们现在真正处理的advisor。
所以接下来进入的方法的第一个参数就是BeanFactoryTransactionAttributeSourceAdvisor的内部属性TransactionAttributeSourcePointcut。
return canApply(pca.getPointcut(), targetClass, hasIntroductions);//入口
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
private TransactionAttributeSource transactionAttributeSource;
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
protected TransactionAttributeSource getTransactionAttributeSource() {
return org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor.this.transactionAttributeSource;
}
};
}
继续接上面代码:
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
//此时的pc表示TransactionAttributeSourcePointcut
//pc.getMethodMatcher()返回的正是自身(this)
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
return true;
}
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
//对于事物的配置不仅仅局限于在函数上配置,我们都知道,在类或接口上的配置可以延续到类中的每个函数
//获取对应类的所有接口
Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
classes.add(targetClass);
//对类进行遍历
for (Class<?> clazz : classes) {
//反射获取类中所有的方法
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
//对类和方法进行增强器匹配
if ((introductionAwareMethodMatcher != null &&
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
methodMatcher.matches(method, targetClass)) {//入口 这个匹配就是找@Transaction注解的过程
return true;
}
}
}
return false;
}
// TransactionAttributeSourcePointcut.matches
public boolean matches(Method method, Class<?> targetClass) {
if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) {
return false;
} else {
TransactionAttributeSource tas = this.getTransactionAttributeSource();
return tas == null || tas.getTransactionAttribute(method, targetClass) != null;
}
}
AbstractFallbackTransactionAttributeSource.getTransactionAttribute:做了一层缓存
@Override
public TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass) {
if (method.getDeclaringClass() == Object.class) {
return null;
}
// First, see if we have a cached value.
Object cacheKey = getCacheKey(method, targetClass);
TransactionAttribute cached = this.attributeCache.get(cacheKey);
if (cached != null) {
// Value will either be canonical value indicating there is no transaction attribute,
// or an actual transaction attribute.
if (cached == NULL_TRANSACTION_ATTRIBUTE) {
return null;
}
else {
return cached;
}
}
else {
// We need to work it out.
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);//入口
// Put it in the cache.
if (txAttr == null) {
this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
}
else {
String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
if (txAttr instanceof DefaultTransactionAttribute) {
((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);
}
if (logger.isDebugEnabled()) {
logger.debug("Adding transactional method ‘" + methodIdentification + "‘ with attribute: " + txAttr);
}
this.attributeCache.put(cacheKey, txAttr);
}
return txAttr;
}
}
@Nullable
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
/**
* 如果方法中存在事务属性,则使用方法上的属性,否则使用方法所在的类上的属性,
* 如果方法所在类的属性上还是没有搜寻到对应的事务属性,那么在搜寻接口中的方法,
* 再没有的话,最后尝试搜寻接口的类上面的声明
*/
// method代表接口中的方法,specificMethod代表实现类中的方法
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
// 查看方法中是否存在事务声明
TransactionAttribute txAttr = findTransactionAttribute(specificMethod);//入口
if (txAttr != null) {
return txAttr;
}
// 查看方法所在类中是否存在事务声明
txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());//入口
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
// 如果存在接口,则到接口中去寻找
if (specificMethod != method) {
// 查找接口方法
txAttr = findTransactionAttribute(method);
if (txAttr != null) {
return txAttr;
}
// 到接口中的类中去寻找
txAttr = findTransactionAttribute(method.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
}
return null;
}
AnnotationTransactionAttributeSource.findTransactionAttribute:
@Override
protected TransactionAttribute findTransactionAttribute(Method method) {
return determineTransactionAttribute(method);
}
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
if (element.getAnnotations().length > 0) {
for (TransactionAnnotationParser annotationParser : this.annotationParsers) {
TransactionAttribute attr = annotationParser.parseTransactionAnnotation(element);
if (attr != null) {
return attr;
}
}
}
return null;
}
@Override
@Nullable
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae) {
AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
ae, Transactional.class, false, false);
if (attributes != null) {
return parseTransactionAnnotation(attributes);
}
else {
return null;
}
}
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
/***
* 首先会判断当前的类是否含有 Transactional注解,这是事务属性的基础,
* 当然如果有的话会继续调用parseTransactionAnnotation 方法解析详细的属性。
*/
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
Propagation propagation = attributes.getEnum("propagation");
// 解析propagation
rbta.setPropagationBehavior(propagation.value());
Isolation isolation = attributes.getEnum("isolation");
// 解析isolation
rbta.setIsolationLevel(isolation.value());
// 解析timeout
rbta.setTimeout(attributes.getNumber("timeout").intValue());
// 解析readOnly
rbta.setReadOnly(attributes.getBoolean("readOnly"));
// 解析value
rbta.setQualifier(attributes.getString("value"));
ArrayList<RollbackRuleAttribute> rollBackRules = new ArrayList<>();
// 解析rollbackFor
Class<?>[] rbf = attributes.getClassArray("rollbackFor");
for (Class<?> rbRule : rbf) {
RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);
rollBackRules.add(rule);
}
// 解析rollbackForClassName
String[] rbfc = attributes.getStringArray("rollbackForClassName");
for (String rbRule : rbfc) {
RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);
rollBackRules.add(rule);
}
// 解析noRollbackFor
Class<?>[] nrbf = attributes.getClassArray("noRollbackFor");
for (Class<?> rbRule : nrbf) {
NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);
rollBackRules.add(rule);
}
// 解析noRollbackForClassName
String[] nrbfc = attributes.getStringArray("noRollbackForClassName");
for (String rbRule : nrbfc) {
NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);
rollBackRules.add(rule);
}
rbta.getRollbackRules().addAll(rollBackRules);
return rbta;
}
通过代理类调用方法的流程
最终执行的是链条中每个advice的invoke方法。回顾前面spring容器初始化过程声明的三个bean,其中TransactionInterceptor就是代表advice的。所以最终执行的是它的invoke方法。
// TransactionInterceptor
@Override
public Object invoke(final MethodInvocation invocation) throws Throwable {
// Work out the target class: may be {@code null}.
// The TransactionAttributeSource should be passed the target class
// as well as the method, which may be from an interface.
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
// Adapt to TransactionAspectSupport‘s invokeWithinTransaction...
return invokeWithinTransaction(invocation.getMethod(), targetClass, new TransactionAspectSupport.InvocationCallback() {
@Override
public Object proceedWithInvocation() throws Throwable {
return invocation.proceed();
}
});
}
以上是关于spring事务的主要内容,如果未能解决你的问题,请参考以下文章
使用 OnItemClickListener 列出视图片段到片段事务