<!-- 声明式事务 -->
<bean name="txmanager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<!-- 事务开启必须使用session -->
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- 事务增强类
transaction-manager:这种机制要放到上面哪一个bean中,
transaction-manager如果不写有一个默认值transactionManager,此时必须保证声明式事务中的bean的名字是transactionManager
-->
<tx:advice id="txAdvice" transaction-manager="txmanager">
<tx:attributes>
<!-- REQUIRED: 第一种事务声明方式,需要事务
SUPPORTS:第四种声明方式,不需要事务-->
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="get*" propagation="SUPPORTS"/>
<tx:method name="find*" propagation="SUPPORTS"/>
<!-- 匹配以上之外的所有方法,类似于switch的default -->
<tx:method name="*" propagation="SUPPORTS"/>
</tx:attributes>
</tx:advice>
<!-- 使用AOP切面,开始把事务添加到切面中 -->
<aop:config>
<!-- 表达式:返回类型模式是*,它代表了匹配任意的返回类型
应用到service下所有实现类的所有类的所有方法所有参数 -->
<aop:pointcut expression="execution(* com.bdqn.ssh.service.impl.*.* (..))" id="mypoint"/>
<!-- 织入 把管理类[txmanager]生成的代理[txAdvice],织入到所定义的切面[mypoint]中 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="mypoint"/>
</aop:config>
一、前言
本节我们来谈谈 <tx:advice/>、<aop:config>
标签如何创建事务切面的。
二、 <tx:advice/>、<aop:config>标签如何创建事务切面的
首先 <tx:advice/>
标签作用是创建一个TransactionInterceptor,作为事务切面的通知方法 在Spring中(可以参考:https://gitbook.cn/gitchat/activity/5a8fdf6bf2e5dc2ca621a937) Advisor这个概念是从 Spring 1.2的 AOP 支持中提出的,一个 Advisor 相当于一个小型的切面,不同的是它只有一个通知(Advice),Advisor中还包含一个pointcut(切点),切点定义了对那些方法进行拦截,而通知是具体对拦截到的方法进行增强的逻辑。
具体对 <tx:advice/>
标签进行解析的是TxAdviceBeanDefinitionParser,其时序图如下:
首先TxAdviceBeanDefinitionParser有getBeanClass方法代码代码:
1. protected Class<?> getBeanClass(Element element) {
2. return TransactionInterceptor.class;
3. }
这说明该标签解析后生成的是TransactionInterceptor对象的bean定义。
-
其中时序图中步骤(2)是设置配置demo的XML配置文件里面创建的事务管理器到TransactionInterceptor对象, -
时序图(4)~(10)则解析<tx:advice/>
标签中事务属性值设置到TransactionInterceptor对象里面属性里面。
注:也就是 <tx:advice/>
标签的作用是生成一个TransactionInterceptor拦击器对象,并设置该对象的一些事务属性,然后该对象将作为事务切面的通知方法。
然后 <aop:config>
标签作用是创建一个DefaultBeanFactoryPointcutAdvisor(其实现了Advisor接口)对象作为作一个Advisor,前面说了一个Advisor就是一个小型的切面,所以其中定义了切点和通知。该标签是ConfigBeanDefinitionParser类进行解析的,其时序图如下:
-
时序图中步骤(2)创建了一个DefaultBeanFactoryPointcutAdvisor对象的bean定义,步骤(3)(4)则是设置上面创建的通知对象(TransactionInterceptor)到该Advisor
-
时序图中步骤(8)则是解析标签中的切点表达式,然后设置到DefaultBeanFactoryPointcutAdvisor对象的bean定义。
-
时序图步骤(4)注册了一个AspectJAwareAdvisorAutoProxyCreator到Spring容器,作用就是对满足pointcut表达式的类的方法进行代理,并且使用advice进行拦截处理,而advice就是事务拦截器。
由于AspectJAwareAdvisorAutoProxyCreator类实现了BeanPostProcessor接口,所以具有postProcessAfterInitialization方法,而对符合切点的方法进行代理就是在该方法内的wrapIfNecessary方法:
1. protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
2. ...
3. // 8.1
4. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
5. if (specificInterceptors != DO_NOT_PROXY) {
6. this.advisedBeans.put(cacheKey, Boolean.TRUE);
7. //8.2
8. Object proxy = createProxy(
9. bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
10. this.proxyTypes.put(cacheKey, proxy.getClass());
11. return proxy;
12. }
13.
14. this.advisedBeans.put(cacheKey, Boolean.FALSE);
15. return bean;
16. }
其中8.1查找所有可以对当前bean进行增强的切面,其中有一个条件就是看那些bean实现了Advisor接口,而 <aop:config>
标签作用是创建一个DefaultBeanFactoryPointcutAdvisor,并且其实现了Advisor接口,所以这里会使用DefaultBeanFactoryPointcutAdvisor切面,然后会看当前bean的方法是否满足切面的切点表达式,具体是AopUtils的canApply方法进行判断:
如果满足则执行8.2对方法进行代理,这里会对TestTransactionProgagationUserImpl、TestTransactionProgagationCourseImpl、UserManagerBoImpl类的所有方法进行事务代理。
注:Spring框架中一个 Advisor 相当于一个小型的切面, <tx:advice/>
定义了这个切面的通知方法,而 <aop:config>
具体定义了一个Advisor切面,并且内部定义了一个切点,并且引入了 <tx:advice/>
定义的通知方法