没有合适的资源?快使用搜索试试~ 我知道了~
Spring源码学习十二:@Transactional是如何工作的1
需积分: 0 0 下载量 82 浏览量
2022-08-04
15:34:13
上传
评论
收藏 737KB PDF 举报
温馨提示
试读
1页
Spring源码学习十二:@Transactional是如何工作的1
资源推荐
资源详情
资源评论
结合Spring框架,在进数据库操作的时候,经常会使@Transactional注解,本篇将深源码
分析@Transactional注解的作原。
先从<tx:annotation-driven/>说起。配置<tx:annotation-driven/>,就必定有对应的标签解析
类,查看NamespaceHandler接的实现类,可以看到个TxNamespaceHandler,它注册
AnnotationDrivenBeanDefinitionParser对annotation-driven元素进解析。
进AnnotationDrivenBeanDefinitionParser类,重点看parse法。
从代码中可以看出,如果<tx:annotation-driven/>中没有配置mode参数,则默认使代模式进
后续处;如果配置mode=aspectj,则使aspectj代码织模式进后续处。
本篇分析使代模式的代码,进AopAutoProxyConfigurer.configureAutoProxyCreator法。
上图代码中标出核代码,容被忽。进
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary法。
重点关注上图中标出的代码,进AopConfigUtils.registerAutoProxyCreatorIfNecessary法。
上图中的代码向Spring容中注册个InfrastructureAdvisorAutoProxyCreator类。可能会疑
问为么要注册这个类,有么作?查看InfrastructureAdvisorAutoProxyCreator类继承关
系。
通过上图中的关系,可以发现InfrastructureAdvisorAutoProxyCreator间接实现
BeanPostProcessor接,从AbstractAutoProxyCreator类中继承
postProcessAfterInitialization法。Spring容在初始化每个单bean的时候,会遍历容中的
所有BeanPostProcessor实现类,并执其postProcessAfterInitialization法。
进AbstractAutoProxyCreator类的postProcessAfterInitialization法。
其中wrapIfNecessary法是创建代对象的核法。
getAdvicesAndAdvisorsForBean法会遍历容中所有的切,查找与当前实化bean匹配的
切,这就是获取事务属性切,查找@Transactional注解及其属性值,具体实现较复杂,
这暂深分析,最终会得到BeanFactoryTransactionAttributeSourceAdvisor实,然后根据
得到的切进createProxy法,创建个AOP代。
进ProxyFactory.getProxy法。
createAopProxy法决定使JDK还是Cglib创建代。
可以看出默认是使JDK动态代创建代,如果标类是接,则使JDK动态代,否则使
Cglib。
这分析使JDK动态代的式,进JdkDynamicAopProxy.getProxy法。
可以看到很熟悉的创建代的代码Proxy.newProxyInstance。这要注意的是,
newProxyInstance法的最后个参数是JdkDynamicAopProxy类本身,也就是说在对标类进
调的时候,会进JdkDynamicAopProxy的invoke法。
这只关注JdkDynamicAopProxy的invoke法的重点代码。
this.advised.getInterceptorsAndDynamicInterceptionAdvice获取的是当前标法对应的拦截
,是根据之前获取到的切来获取相对应拦截,这时候会得到TransactionInterceptor实
。如果获取到拦截,则会创建MethodInvocation,直接调标法。这使
TransactionInterceptor创建个ReflectiveMethodInvocation实,调的时候进
ReflectiveMethodInvocation的proceed法。
代码中的interceptorOrInterceptionAdvice就是TransactionInterceptor的实,执invoke法进
TransactionInterceptor的invoke法。
TransactionInterceptor从类TransactionAspectSupport中继承invokeWithinTransaction
法。
可以看到,在需要进事务操作的时候,Spring会在调标类的标法之前进开启事务、
调异常回滚事务、调完成会提交事务。
是否需要开启新事务,是根据@Transactional注解上配置的参数值来判断的。如果需要开启新事
务,获取Connection连接,然后将连接的动提交事务改为false,改为动提交。
当对标类的标法进调的时候,若发异常将会进
completeTransactionAfterThrowing法。
Spring并会对所有类型异常都进事务回滚操作,默认是只对Unchecked Exception(Error和
RuntimeException)进事务回滚操作。
总结
从上的分析可以看到,Spring使AOP实现事务的统管,为开发者提供很的。但
是,有部分开发员会误这个,基本都是下这两种情况:
1.A类的a1法没有标注@Transactional,a2法标注@Transactional,在a1调a2;
2.将@Transactional注解标注在public法上。
第种为么是错误法,原因很简单,a1法是标类A的原法,调a1的时候即直接进
标类A进调,在标类A只有a2的原法,在a1调a2,即直接执a2的原
法,并通过创建代对象进调,所以并会进TransactionInterceptor的invoke法,
会开启事务。
@Transactional的作机制是基于AOP实现的,AOP是使动态代实现的,动态代要么是
JDK式、要么是Cglib式。如果是JDK动态代的式,根据上的分析可以知道,标类的
标法是在接中定义的,也就是必须是public修饰的法才可以被代。如果是Cglib式,
代类是标类的类,论上可以代public和protected法,但是Spring在进事务增强是
否能够应到当前标类判断的时候,遍历的是标类的public法,所以Cglib式也只对
public法有效。
深Class类getMethods法,可以看到取得是public修饰的法。
资源评论
天眼妹
- 粉丝: 21
- 资源: 333
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功