Spring源代码解析6Spring声明式事务处理.docx
- 文档编号:30146645
- 上传时间:2023-08-05
- 格式:DOCX
- 页数:21
- 大小:22.41KB
Spring源代码解析6Spring声明式事务处理.docx
《Spring源代码解析6Spring声明式事务处理.docx》由会员分享,可在线阅读,更多相关《Spring源代码解析6Spring声明式事务处理.docx(21页珍藏版)》请在冰豆网上搜索。
Spring源代码解析6Spring声明式事务处理
我们看看Spring中的事务处理的代码,使用Spring管理事务有声明式和编程式两种方式,声明式事务处理通过AOP的实现把事物管理代码作为方面封装来横向插入到业务代码中,使得事务管理代码和业务代码解藕。
在这种方式我们结合IoC容器和Spirng已有的FactoryBean来对事务管理进行属性配置,比如传播行为,隔离级别等。
其中最简单的方式就是通过配置TransactionProxyFactoryBean来实现声明式事物;
在整个源代码分析中,我们可以大致可以看到Spring实现声明式事物管理有这么几个部分:
*对在上下文中配置的属性的处理,这里涉及的类是TransactionAttributeSourceAdvisor,这是一个通知器,用它来对属性值进行处理,属性信息放在TransactionAttribute中来使用,而这些属性的处理往往是和对切入点的处理是结合起来的。
对属性的处理放在类TransactionAttributeSource中完成。
*创建事物的过程,这个过程是委托给具体的事物管理器来创建的,但Spring通过TransactionStatus来传递相关的信息。
*对事物的处理通过对相关信息的判断来委托给具体的事物管理器完成。
我们下面看看具体的实现,在TransactionFactoryBean中:
代码
1.public class TransactionProxyFactoryBean extends AbstractSingletonProxyFactoryBean
2. implements FactoryBean, BeanFactoryAware {
3.//这里是Spring事务处理而使用的AOP拦截器,中间封装了Spring对事务处理的代码来支持声明式事务处理的实现
4. private final TransactionInterceptor transactionInterceptor = new TransactionInterceptor();
5.
6. private Pointcut pointcut;
7.
8.//这里Spring把TransactionManager注入到TransactionInterceptor中去
9. public void setTransactionManager(PlatformTransactionManager transactionManager) {
10. this.transactionInterceptor.setTransactionManager(transactionManager);
11. }
12.
13.//这里把在bean配置文件中读到的事务管理的属性信息注入到TransactionInterceptor中去
14. public void setTransactionAttributes(Properties transactionAttributes) {
15. this.transactionInterceptor.setTransactionAttributes(transactionAttributes);
16. }
17.
18. .........中间省略了其他一些方法.......
19.
20. //这里创建Spring AOP对事务处理的Advisor
21. protected Object createMainInterceptor() {
22. this.transactionInterceptor.afterPropertiesSet();
23. if (this.pointcut !
= null) {
24. //这里使用默认的通知器
25. return new DefaultPointcutAdvisor(this.pointcut, this.transactionInterceptor);
26. }
27. else {
28. // 使用上面定义好的TransactionInterceptor作为拦截器,同时使用TransactionAttributeSourceAdvisor
29. return new TransactionAttributeSourceAdvisor(this.transactionInterceptor);
30. }
31. }
32.}
那什么时候Spring的TransactionInterceptor被注入到SpringAOP中成为Advisor中的一部分呢?
我们看到在TransactionProxyFactoryBean中,这个方法在IOC初始化bean的时候被执行:
代码
1.public void afterPropertiesSet() {
2. .......
3. //TransactionProxyFactoryBean实际上使用ProxyFactory完成AOP的基本功能。
4. ProxyFactory proxyFactory = new ProxyFactory();
5.
6. if (this.preInterceptors !
= null) {
7. for (int i = 0; i < this.preInterceptors.length; i++) {
8. proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(this.preInterceptors[i]));
9. }
10. }
11.
12. //这里是Spring加入通知器的地方
13. //有两种通知器可以被加入DefaultPointcutAdvisor或者TransactionAttributeSourceAdvisor
14. //这里把Spring处理声明式事务处理的AOP代码都放到ProxyFactory中去,怎样加入advisor我们可以参考ProxyFactory的父类AdvisedSupport()
15. //由它来维护一个advice的链表,通过这个链表的增删改来抽象我们对整个通知器配置的增删改操作。
16. proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(createMainInterceptor()));
17.
18. if (this.postInterceptors !
= null) {
19. for (int i = 0; i < this.postInterceptors.length; i++) {
20. proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(this.postInterceptors[i]));
21. }
22. }
23.
24. proxyFactory.copyFrom(this);
25.
26. //这里创建AOP的目标源
27. TargetSource targetSource = createTargetSource(this.target);
28. proxyFactory.setTargetSource(targetSource);
29.
30. if (this.proxyInterfaces !
= null) {
31. proxyFactory.setInterfaces(this.proxyInterfaces);
32. }
33. else if (!
isProxyTargetClass()) {
34. proxyFactory.setInterfaces(ClassUtils.getAllInterfacesForClass(targetSource.getTargetClass()));
35. }
36.
37. this.proxy = getProxy(proxyFactory);
38.}
Spring已经定义了一个transctionInterceptor作为拦截器或者AOPadvice的实现,在IOC容器中定义的其他属性比如transactionManager和事务管理的属性都会传到已经定义好的TransactionInterceptor那里去进行处理。
以上反映了基本的SpringAOP的定义过程,其中pointcut和advice都已经定义好,同时也通过通知器配置到ProxyFactory中去了。
下面让我们回到TransactionProxyFactoryBean中看看TransactionAttributeSourceAdvisor是怎样定义的,这样我们可以理解具体的属性是怎样起作用,这里我们分析一下类TransactionAttributeSourceAdvisor:
代码
1.public class TransactionAttributeSourceAdvisor extends AbstractPointcutAdvisor {
2. //和其他Advisor一样,同样需要定义AOP中的用到的Interceptor和Pointcut
3. //Interceptor使用传进来的TransactionInterceptor
4. //而对于pointcut,这里定义了一个内部类,参见下面的代码
5. private TransactionInterceptor transactionInterceptor;
6.
7. private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut();
8.
9. .........
10. //定义的PointCut内部类
11. private class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
12. .......
13. //方法匹配的实现,使用了TransactionAttributeSource类
14. public boolean matches(Method method, Class targetClass) {
15. TransactionAttributeSource tas = getTransactionAttributeSource();
16. //这里使用TransactionAttributeSource来对配置属性进行处理
17. return (tas !
= null && tas.getTransactionAttribute(method, targetClass) !
= null);
18. }
19. ........省略了equal,hashcode,tostring的代码
20. }
这里我们看看属性值是怎样被读入的:
AbstractFallbackTransactionAttributeSource负责具体的属性读入任务,我们可以有两种读入方式,比如annotation和直接配置.我们下面看看直接配置的读入方式,在Spring中同时对读入的属性值进行了缓存处理,这是一个decorator模式:
代码
1.public final TransactionAttribute getTransactionAttribute(Method method, Class targetClass) {
2. //这里先查一下缓存里有没有事务管理的属性配置,如果有从缓存中取得TransactionAttribute
3. Object cacheKey = getCacheKey(method, targetClass);
4. Object cached = this.cache.get(cacheKey);
5. if (cached !
= null) {
6. if (cached == NULL_TRANSACTION_ATTRIBUTE) {
7. return null;
8. }
9. else {
10. return (TransactionAttribute) cached;
11. }
12. }
13. else {
14. // 这里通过对方法和目标对象的信息来计算事务缓存属性
15. TransactionAttribute txAtt = computeTransactionAttribute(method, targetClass);
16. //把得到的事务缓存属性存到缓存中,下次可以直接从缓存中取得。
17. if (txAtt == null) {
18. this.cache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
19. }
20. else {
21. ...........
22. this.cache.put(cacheKey, txAtt);
23. }
24. return txAtt;
25. }
26.}
别急,基本的处理在computeTransactionAttribute()中:
代码
1.private TransactionAttribute computeTransactionAttribute(Method method, Class targetClass) {
2. //这里检测是不是public方法
3. if(allowPublicMethodsOnly() && !
Modifier.isPublic(method.getModifiers())) {
4. return null;
5. }
6.
7. Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
8.
9. // First try is the method in the target class.
10. TransactionAttribute txAtt = findTransactionAttribute(findAllAttributes(specificMethod));
11. if (txAtt !
= null) {
12. return txAtt;
13. }
14.
15. // Second try is the transaction attribute on the target class.
16. txAtt = findTransactionAttribute(findAllAttributes(specificMethod.getDeclaringClass()));
17. if (txAtt !
= null) {
18. return txAtt;
19. }
20.
21. if (specificMethod !
= method) {
22. // Fallback is to look at the original method.
23. txAtt = findTransactionAttribute(findAllAttributes(method));
24. if (txAtt !
= null) {
25. return txAtt;
26. }
27. // Last fallback is the class of the original method.
28. return findTransactionAttribute(findAllAttributes(method.getDeclaringClass()));
29. }
30. return null;
31.}
经过一系列的尝试我们可以通过findTransactionAttribute()通过调用findAllAttribute()得到TransactionAttribute的对象,如果返回的是null,这说明该方法不是我们需要事务处理的方法。
在完成把需要的通知器加到ProxyFactory中去的基础上,我们看看具体的看事务处理代码怎样起作用,在TransactionInterceptor中:
代码
1.public Object invoke(final MethodInvocation invocation) throws Throwable {
2. //这里得到目标对象
3. Class targetClass = (invocation.getThis() !
= null ?
invocation.getThis().getClass() :
null);
4.
5. //这里同样的通过判断是否能够得到TransactionAttribute来决定是否对当前方法进行事务处理,有可能该属性已经被缓存,
6. //具体可以参考上面对getTransactionAttribute的分析,同样是通过TransactionAttributeSource
7. final TransactionAttribute txAttr =
8. getTransactionAttributeSource().getTransactionAttribute(invocation.getMethod(), targetClass);
9. final String joinpointIdentification = methodIdentification(invocation.getMethod());
10.
11. //这里判断我们使用了什么TransactionManager
12. if (txAttr == null || !
(getTransactionManager() instanceof CallbackPreferringPlatformTransactionManager)) {
13. // 这里创建事务,同时把创建事务过程中得到的信息放到TransactionInfo中去
14. TransactionInfo txInfo = createTransactionIfNecessary(txAttr, joinpointIdentification);
15. Object retVal = null;
16. try {
17. retVal = invocation.proceed();
18. }
19. catch (Throwable ex) {
20. // target invocation exception
21. completeTransactionAfterThrowing(txInfo, ex);
22. throw ex;
23. }
24. finally {
25. cleanupTransactionInfo(txInfo);
26. }
27. commitTransactionAfterReturning(txInfo);
28. return retVal;
29. }
30.
31. else {
32. // 使用的是Spring定义的PlatformTransactionManager同时实现了回调接口,我们通过其回调函数完成事务处理,就像我们使用编程式事务处理一样。
33. try {
34. Object result = ((CallbackPr
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Spring 源代码 解析 声明 事务处理