配置方式实现事物管理

来源:互联网 发布:原始对偶知乎 编辑:程序博客网 时间:2024/06/05 06:47

接着上一篇博客。。。。

在Spring2.x之前为了解决编程式事务管理的各种不好问题,Spring提出使用配置方式实现事务管理,配置方式利用代理机制实现,即使有TransactionProxyFactoryBean类来为目标类代理事务管理。

1、重新定义业务实现类,在业务类中无需显示的事物管理代码

public class ConfigUserServiceImpl implements IUserService{private IUserDAO userDAO;private IAdressService adressService;public void setUserDAO(IUserDAO userDAO) {this.userDAO = userDAO;}public void setAdressService(IAdressService adressService) {this.adressService = adressService;}@Overridepublic void save(UserModel user) {KeyHolder key=userDAO.save(user);user.getAddress().setUserid( key.getKey().intValue());adressService.save(user.getAddress());}@Overridepublic int countAll() {return userDAO.countAll();}}


public class ConfigAddressServiceImpl implements IAdressService{private IAdressDAO adressDAO;public void setAdressDAO(IAdressDAO adressDAO) {this.adressDAO = adressDAO;}@Overridepublic void save(final AddressModel address) {adressDAO.save(address);}@Overridepublic int countAll() {return adressDAO.countAll();}}
从以上业务类中可以看出,没有事务管理的代码,即没有侵入式的代码。


2、在配置文件中添加目标 类定义


        <!-- 下面是沒有事物管理的業務類的配置 --><bean id="targetUserService" class="com.spring.serviceImpl.ConfigUserServiceImpl"><property name="userDAO" ref="userDAO"></property><property name="adressService" ref="targetAddressService"></property></bean><bean id="targetAddressService" class="com.spring.serviceImpl.ConfigAddressServiceImpl"><property name="adressDAO" ref="addressDAO"></property></bean>


3、配置TransactionProxyFactoryBean类

        <!-- 配置TransactionProxyFactoryBean類 --><!-- TransactionProxyFactoryBean:用于为目标业务类创建代理的Bean; --><!-- abstract="true":表示该Bean是抽象的,用于去除重复配置; --><bean id="transactionProxyParent"class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"abstract="true"><property name="transactionManager" ref="txManager"></property><property name="transactionAttributes"><props><prop key="save*">PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED,timeout_10,-Exception,+NoRollBackException</prop><prop key="*">PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED,readOnly</prop></props></property></bean>

TransactionProxyFactoryBean:用于为目标业务类创建代理的Bean;
abstract="true":表示该Bean是抽象的,用于去除重复配置;
transactionManager:事务管理器定义;
transactionAttributes:表示事务属性定义:
PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED,timeout_10,-Exception,+NoRollBackException:事务属性定义,Required传播行为,提交读隔离级别,
事务超时时间为10秒,将对所有Exception异常回滚,而对于抛出NoRollBackException异常将不发生回滚而是提交
PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED,readOnly:事务属性定义,Required传播行为,提交读隔离级别,事务是只读的,且只对默认的RuntimeException异常回滚;
<prop key="save*">:表示将代理以save开头的方法,即当执行到该方法时会为该方法根据事务属性配置来开启/关闭事务;
<prop key="*">:表示将代理其他所有方法,但需要注意代理方式,默认是JDK代理,只有public方法能代理;


4、定义代理bean

        <!-- 定义代理bean --><bean id="proxyUserService" parent="transactionProxyParent"><property name="target" ref="targetUserService"></property></bean><bean id="proxyAddressService" parent="transactionProxyParent"><property name="target" ref="targetAddressService"></property></bean>
代理Bean通过集成抽象Bean“transactionProxyParent”,并通过target属性设置目标Bean,在实际使用中应该使用该代理Bean。


5、测试

        /** * 聲明式事物測試 */@Testpublic void configTest() {ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");IUserService userService = (IUserService) ctx.getBean("proxyUserService");IAdressService addressService = (IAdressService) ctx.getBean("proxyAddressService");UserModel user = createDefaultUserModel();userService.save(user);}

代理方式实现事务管理只是将硬编码的事务管理代码转移到代理中去由代理实现,在代理中实现事务管理。
在代理模式下,默认只有通过代理对象调用的方法才能应用相应的事务属性,而在目标方法内的“自我调用”是不会应用相应的事务属性的,即被调用方法不会应用相应的事务属性,而是使用调用方法的事务属性。


使用声明式事物管理,使用以下4种配置方式在IoC容器配置文件中指定事物需要的元数据
使用ProxyFactory+TransactionInterceptor
使用一站式的TransactionProxyFactoryBean
使用BeanNameAutoProxyCreator
使用Spring2.x的声明式事物配置方式


其实事物管理本身就是一种横切关注点,与其他横切关注点本质上没有任何区别,所以我们完全可以为其提供相应的Advice
实现,然后织入到系统中需要改=该横切关注的JoinPoint处,这样就达到了将事物管理逻辑从业务逻辑实现中分离出来的目的
。现在要做的就是需要提供一个拦截器,在业务方法实行开始之前开启一个事物,当方法执行完或异常退出的时候就提交事物
或回滚事物。

0 0
原创粉丝点击