Spring框架引人注目的重要因素之一是它全面的事务支持。Spring框架提供了一致的事务管理抽象,这带来了以下好处:
为复杂的事务API提供了一致的编程模型,如JTA、JDBC、Hibernate、JPA和JDO
支持 声明式事务管理
提供比大多数复杂的事务API(诸如JTA)更简单的,更易于使用的 编程式 事务管理API
非常好地整合Spring的各种数据访问抽象
传统上,J2EE开发者有两个事务管理的选择: 全局 或 本地 事务。
全局事务由应用服务器管理,使用JTA。
局部事务是和资源相关的,比如一个和JDBC连接关联的事务。这个选择有深刻的含义。
例如,全局事务可以用于多个事务性的资源(典型例子是关系数据库和消息队列)。
使用局部事务,应用服务器不需要参与事务管理,并且不能帮助确保跨越多个资源(需要指出的是多数应用使用单一事务性的资源)的事务的正确性。
全局事务有一个重大的缺陷,代码需要使用JTA:一个笨重的API(部分是因为它的异常模型)。此外,JTA的UserTransaction通常需要从JNDI获得,这意味着我们为了JTA,需要 同时 使用JNDI 和 JTA。
使用全局事务的首选方式是通过EJB的 CMT(容器管理事务):CMT是 声明式事务管理 的一种形式(区别于 编程式事务管理)。
重大的缺陷是CMT绑定在JTA和应用服务器环境上,并且只有我们选择使用EJB实现业务逻辑,或者至少处于一个事务化EJB的外观(Facade)后才能使用它。
本地事务. 本地事务容易使用,但也有明显的缺点:它们不能用于多个事务性资源。
例如,使用JDBC连接事务管理的代码不能用于全局的JTA事务中。
另一个缺点是局部事务趋向于入侵式的编程模型。
Spring解决了这些问题。它使应用开发者能够使用在 任何环境 下使用 一致 的编程模型.Spring框架同时提供声明式和编程式事务管理。声明事务管理是多数使用者的首选,在多数情况下是被推荐使用的。
如何解决??AOP?回调
使用编程式事务管理,开发者直接使用Spring框架事务抽象,这个抽象可以使用在任何底层事务基础之上。
使用首选的声明式模型,开发者通常书写很少的或没有与事务相关的代码,因此不依赖Spring框架或任何其他事务API。
Spring事务抽象的关键是事务策略的概念。这个概念由org.springframework.transaction.PlatformTransactionManager接口定义。
TransactionStatus 对象可能代表一个新的或已经存在的事务(如果在当前调用堆栈有一个符合条件的事务。如同J2EE事务环境,一个 TransactionStatus 也是和执行 线程 绑定的)。
TransactionDefinition接口指定:
1、事务隔离:当前事务和其它事务的隔离的程度。例如,这个事务能否看到其他事务未提交的写数据?
2、事务传播:通常在一个事务中执行的所有代码都会在这个事务中运行。但是,如果一个事务上下文已经存在,有几个选项可以指定一个事务性方法的执行行为:例如,简单地在现有的事务中继续运行(大多数情况);或者挂起现有事务,创建一个新的事务。Spring提供EJB CMT中常见的事务传播选项。
3、事务超时: 事务在超时前能运行多久(自动被底层的事务基础设施回滚)。
4、只读状态: 只读事务不修改任何数据。只读事务在某些情况下(例如当使用Hibernate时),是一种非常有用的优化。
这些设置反映了标准概念。
事务的四个特性:原子、一致、隔离、持久。
TransactionStatus 接口为处理事务的代码提供一个简单的控制事务执行和查询事务状态的方法。
使用Spring时,无论你选择编程式还是声明式的事务管理,定义一个正确的 PlatformTransactionManager 实现都是至关重要的。
按照Spring的良好风格,这种重要定义都是通过IoC实现的。
一般来说,选择PlatformTransactionManager实现时需要知道当前的工作环境,如JDBC、JTA、Hibernate等。
局部事务:我们需要定义一个Hibernate的 LocalSessionFactoryBean,应用程序从中获取到Hibernate Session 实例。
如果是一个JEE容器提供的 DataSource,它将由JEE容器自身,而不是Spring框架来管理事务。????
这种情况中'txManager' bean的类型为 HibernateTransactionManager。同样地,DataSourceTransactionManager 需要一个指向 DataSource 的引用,而 HibernateTransactionManager 需要一个指向 SessionFactory 的引用。
JEE容器提供的 DataSource????全局事务确认。全局事务,可以支持任何事务性资源。
现在应该比较清楚的是:不同的事务管理器是如何创建的,以及它们如何被连接到相应的需要被同步到事务的资源上。
剩下的问题是:直接或间接地使用一种持久化API(JDBC、Hibernate、JDO等)的应用代码,如何确保通过相关的 PlatformTransactionManager 来恰当地获取并操作资源,来满足事务同步,这些操作包括:创建、复用、清理 和 触发(可能没有)。
高层次方案:
首选的方法是使用Spring的高层持久化集成API。对所有持久化API都采用这种 模板 方法,包括 JdbcTemplate、HibernateTemplate和JdoTemplate类.
低层次方案
在较低层次上,有以下这些类:DataSourceUtils(针对JDBC),SessionFactoryUtils(针对Hibernate),PersistenceManagerFactoryUtils(针对JDO)等等。
当对应用代码来说,直接同原始持久化API特有的资源类型打交道是更好的选择时,这些类确保应用代码获取到正确的Spring框架所管理的bean,事务被正确同步,处理过程中的异常被映射到一致的API。
保证了跨数据库——甚至其他持久化技术——的移植性。
这些类同样可以在没有Spring事务管理的环境中工作良好(事务同步能力是可选的),所以无论你是否使用Spring的事务管理,你都可以使用这些类。
DataAccessExceptions好处?
声明式事务管理:
最符合 非侵入式 轻量级容器的理念。
Spring的声明式事务管理是通过Spring AOP实现的。
因为事务方面的代码与Spring绑定并以一种样板式风格使用, 不过尽管如此,你一般并不需要理解AOP概念就可以有效地使用Spirng的声明式事务管理。
EJB CMT和Spring声明式事务管理的相似以及不同之处出发是很有益的。重要
回滚规则的概念比较重要:它使我们能够指定什么样的异常(和throwable)将导致自动回滚。
我们在配置文件中声明式地指定,无须在Java代码中。
我们仍旧可以通过调用 TransactionStatus 的 setRollbackOnly() 方法编程式地回滚当前事务。
默认式Spring处理声明式事务管理的规则遵守EJB习惯(只在遇到unchecked exceptions时自动回滚),但通常定制这条规则会更有用。
Spring的事务管理是通过AOP代理实现的。
其中的事务通知由元数据(目前基于XML或注解)驱动。
代理对象与事务元数据结合产生了一个AOP代理,它使用一个PlatformTransactionManager 实现品配合TransactionInterceptor,在方法调用前后实施事务。
推荐做法是在Spring框架的事务架构里指出当context的事务里的代码抛出 Exception 时事务进行回滚。
Spring框架的事务基础架构代码将从调用的堆栈里捕获到任何未处理的 Exception,并将标识事务将回滚。
注意Spring框架的事务基础架构代码将默认地 只 在抛出运行时和unchecked exceptions时才标识事务回滚。
也就是说,当抛出一个 RuntimeException 或其子类例的实例时才会回滚。从事务方法中抛出的Checked exceptions将 不 被标识进行事务回滚。
第一种方法可以配置哪些 Exception类型将被标识进行事务回滚。 no-rollback-for rollback-for
第二种方法是通过 编程式 方式来指定回滚事务。
假设你有许多服务对象,你想为他们分别设置 完全不同 的事务语义。
在Spring中,你可以通过分别定义特定的 <aop:advisor/> 元素, 让每个advisor采用不同的 'pointcut' 和 'advice-ref' 属性,来达到目的。
两个拥有完全不同的事务配置的bean。
默认的 <tx:advice/> 设置如下:
事务传播设置 是 REQUIRED
隔离级别是DEFAULT
事务是 读/写
事务超时默认是依赖于事务系统的,或者事务超时没有被支持。
任何 RuntimeException 将触发事务回滚,但是任何 checked Exception 将不触发事务回滚
除了基于XML文件的声明式事务配置外,你也可以采用基于注解式的事务配置方法。Java 5(Tiger)。
一般配置都有个默认的问题:如果你用 'transactionManager' 来定义 PlatformTransactionManager bean的名字的话,你就可以忽略 <tx:annotation-driven/> 标签里的 'transaction-manager' 属性。 如果 PlatformTransactionManager bean你要通过其它名称来注入的话,你必须用 'transaction-manager' 属性来指定它。
请注意只是使用 @Transactional 注解并不会启用事务行为, 它仅仅 是一种元数据,能够被可以识别 @Transactional 注解和上述的配置适当的具有事务行为的beans所使用。
<tx:annotation-driven/>元素的出现 开启 了事务行为。
Spring团队的建议是你只在具体的类上使用 @Transactional 注解, 而不要注解在接口上。
你当然可以在接口(或接口方法)上使用 @Transactional 注解, 但是这只有在你使用基于接口的代理时它才会生效。
因为注解是 不能继承 的, 这就意味着如果你正在使用基于类的代理时,事务的设置将不能被基于类的代理所识别,而且对象也不会被事务代理所包装 (这是很糟糕的)。
‘自我调用’是不会触发事务的,比如说,一个在目标对象中调用目标对象其他方法的方法是不会触发一个事务的,即使这个方法被标记为 @Transactional!
在多数情形下,方法的事务设置将被优先执行。
在由Spring管理的事务中,请记住 物理 和 逻辑 事务存在的差异, 以及传播设置是如何影响到这些差异的。
获得到一个拥有剖析和事务方面的 。
Spring提供两种方式的编程式事务管理:
1、使用 TransactionTemplate
2、直接使用一个 PlatformTransactionManager 实现
如果你选择编程式事务管理,Spring小组推荐使用 TransactionTemplate。 第二种方法则类似使用JTA的 UserTransaction API
TransactionTemplate 它使用回调机制,将应用代码从样板式的资源获取和释放代码中解放出来, 这样写出的代码是目的驱动的,把精力集中在开发者想要做的事情上。
使用 TransactionTemplate 绝对会增加你的代码与Spring的事务框架和API间的耦合。
写一个 TransactionCallback 的实现, (通常会用匿名类来实现 )这样的实现会包含所以你需要在该事务上下文中执行的代码。
然后把一个实现TransactionCallback的实例传递给TransactionTemplate暴露的execute(..) 方法。
return transactionTemplate.execute(new TransactionCallback() {
// the code in this method executes in a transactional context
public Object doInTransaction(TransactionStatus status) {
updateOperation1();
return resultOfUpdateOperation2();
}
});
如果不需要返回值,更方便的方式是创建一个 TransactionCallbackWithoutResult 的匿名类,如下:
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
updateOperation1();
updateOperation2();
}
});
回调方法内的代码可以通过调用 TransactionStatus 对象的 setRollbackOnly() 方法来回滚事务。
诸如传播模式、隔离等级、超时等等的事务设置都可以在TransactionTemplate中或者通过配置或者编程式地实现。 TransactionTemplate实例默认继承了默认事务设置。
TransactionTemplate 类的实例是线程安全的,任何状态都不会被保存。
可以使用 org.springframework.transaction.PlatformTransactionManager 来直接管理你的事务。
只需通过bean的引用,简单的把你在使用的PlatformTransactionManager 传递给你的bean。
然后,使用TransactionDefinition和TransactionStatus对象, 你可以启动,回滚和提交事务。
只有编程式事务管理才能显式的设置事务名称。
分享到:
相关推荐
AOP 在 Spring.NET 中主要通过代理模式实现,可以用于事务管理、日志记录、性能度量等场景。 总之,Spring.NET 是一个强大的 .NET 开发框架,通过 IoC 和 AOP 提供了灵活的应用程序结构和模块化设计,使开发者能够...
Spring的核心特性之一是控制反转(Inversion of Control, IOC),它将对象的创建和管理交给Spring容器。依赖注入(Dependency Injection, DI)则是实现IOC的一种方式,允许你声明对象之间的依赖关系,而不是在代码...
Spring 提供了面向切面编程的支持,允许开发者定义“切面”,这些切面可以包含业务逻辑的某个方面,比如日志记录、事务管理等。切面可以在多个对象上织入,以实现代码的解耦和复用。Spring 支持通过注解和 XML 配置...
这个"spring5学习代码整理文件"包含了个人在学习Spring5过程中整理的各种代码示例,旨在帮助理解和掌握Spring5的关键概念和技术。 1. **依赖注入(DI)**:Spring5通过DI来解耦应用程序组件,使得组件之间不再硬...
而面向切面编程则提供了在不修改源代码的情况下,添加、修改或增强已有功能的能力,这对于日志记录、事务管理等跨切面的关注点特别有用。 SpringMVC作为Spring框架的一部分,负责处理HTTP请求和响应。它遵循Model-...
2. **AOP**:Spring的AOP模块允许开发者定义横切关注点,例如日志记录、事务管理等,将它们与业务逻辑解耦。 3. **数据访问**:Spring提供了对各种数据库的支持,包括JDBC抽象层、ORM集成(如Hibernate、MyBatis)...
6. **AOP(面向切面编程)**:AOP是Spring的重要特性,它允许我们定义横切关注点,比如日志记录、事务管理等,然后将其编织到业务逻辑中。使用`@Aspect`注解定义切面,`@Before`、`@After`等注解定义切入点,`@...
AOP是Spring提供的另一个重要特性,它允许我们在不修改业务代码的情况下,添加额外的功能,如日志记录、事务管理等。Spring AOP通过切面(Aspect)来实现,切面是跨越多个对象的横切关注点的封装。 三、Bean的配置 ...
- **AOP支持**:Spring的AOP特性用于实现如权限拦截、日志记录等功能。 - **辅助类库**:如JdbcTemplate、HibernateTemplate,简化了数据库操作。 - **框架集成**:Spring能很好地与Hibernate、JPA、Struts等框架...
- **Spring基础知识**:介绍Spring框架的基本概念和核心组件。 - **依赖注入详解**:深入讲解依赖注入的原理及其在Spring中的应用。 - **面向切面编程实践**:教授如何使用Spring AOP进行日志记录、性能监控等。 - *...
在实际开发中,我们可以利用Spring AOP来处理日志记录、事务管理、性能监控等跨切面关注点。例如,对于事务管理,我们可以通过定义一个切面,包含开始事务的前置通知、提交或回滚事务的后置通知,然后通过切入点...
这份“Spring面试专题及答案整理文档”涵盖了Spring框架的关键知识点,包括但不限于基本概念、核心组件、Spring Boot、Spring MVC、数据访问以及Spring Cloud等相关内容。 1. **Spring框架基础** - **依赖注入**:...
这份"spring学习笔记共10页.pdf.zip"压缩包文件,显然包含了关于Spring框架的详细学习资料,可能是由一位经验丰富的开发者或教师精心整理的。在10页的笔记中,我们可以期待涵盖Spring框架的基础概念、核心特性以及...
- **面向切面编程(AOP)**:Spring还支持面向切面编程,这是一种编程范式,旨在将横切关注点(如日志记录、事务管理等)从业务逻辑中分离出来。 #### 1.3. Spring框架中的IoC容器 Spring框架中的IoC容器是实现...
在企业级应用中,事务管理、日志记录、安全控制等往往是横切于各个业务功能的共同需求,AOP通过模块化这些横切关注点,使得主要业务逻辑更加清晰,减少了代码的重复。 #### 二、AOP核心概念解析 AOP的核心概念主要...
7. **阅读笔记**:随书阅读笔记是学习过程中的重要辅助资料,可以帮助读者整理思绪,记录关键点,解决疑惑,提高学习效果。笔记可能包括概念解释、代码示例、问题解答和实战经验分享等。 总的来说,《Spring in ...
这份"Spring学习思维笔记"很可能是整理了Spring框架的关键概念、核心组件以及实际应用中的最佳实践,通过思维导图的形式帮助学习者理解和记忆。 首先,让我们来看看Spring框架的核心知识点: 1. **控制反转(IoC)...
- **定义**:Bean是Spring框架中的核心概念之一,指的是由IoC容器管理的对象。 - **生命周期**:Bean的生命周期包括初始化、使用和销毁三个阶段。 - **配置方式**:可以通过XML文件或注解的方式进行配置。 ### 三、...
课程笔记以Markdown格式记录,便于阅读和整理,可能包括关键代码示例、重要概念解释和课程重点摘要。图片的加入能更直观地展示代码结构和流程图,有助于理解复杂的概念。 总的来说,尚硅谷的Spring Boot课程全面...
面向切面编程允许程序员将横切关注点(如日志记录、事务管理等)从业务逻辑中分离出来,从而提高代码的可读性和可维护性。Spring框架通过AOP代理实现了这一功能,使得开发者可以在不修改业务逻辑代码的情况下添加新...