事务管理和要求

上传人:ni****g 文档编号:586570767 上传时间:2024-09-05 格式:PPT 页数:49 大小:212KB
返回 下载 相关 举报
事务管理和要求_第1页
第1页 / 共49页
事务管理和要求_第2页
第2页 / 共49页
事务管理和要求_第3页
第3页 / 共49页
事务管理和要求_第4页
第4页 / 共49页
事务管理和要求_第5页
第5页 / 共49页
点击查看更多>>
资源描述

《事务管理和要求》由会员分享,可在线阅读,更多相关《事务管理和要求(49页珍藏版)》请在金锄头文库上搜索。

1、事务管理目录n事务管理理解事务在Spring中编写事务声明式事务通过方法名声明事务用元数据声明事务修剪事务声明小结理解事务n实例假设有一个影院票房管理系统,我们定购一张电影票。票房管理系统完成这件事通常要设计到一下几个行为:检查空余位子的数量,以便核实有足够的位子供你购买。卖出一张票,空余位置的数量就减少一个。你为电源票付款。将电影票发给你。如果一切正常,你就可以享受一部大片,而电影院则多了几美元的收入。但是如果有些环节出错了呢?例如,你用一张已经达到限额的信用卡支付,会怎样呢?或者每件事情都正常运行,当时电影票发不出来,将会发生什么事呢?你不会拿到电影票,电影院不会收到你的钱,同时还要将已经

2、发放的座位给取消,以免保证影院座位被虚假的耗尽(避免损失销售额)。为保证不管是你还是电影院不受损失,上面的行为将被限定在一个事务里面。作为一个事务,他们将被视作是一个单一的行为。保证他们每个步骤都是成功的,否则所有动作都被回滚。下面图示展示了事务是如何进行的:验证位子保留位子发电影票接收付款事务被提交事务被回滚每一步骤都正常完成有一个步骤失败了买电影票事务在软件中扮演了一个很重要的角色,确保数据和资源不会处在一种不一致的状态下。没有事务,就可能出现数据的破坏,或者和应用中业务规则不一致。n事务的4个要素:ACID原子性(Atomic):事务由一个或多个行为绑在一起组成,好像是一个单独工作单元。

3、原子性确保在事务中的所有操作要么都发生,要么都不发生。一致性(Consistent):一旦一个事务结束了(不管成功与否),系统所处的状态和他的业务规则是一致的。用现实中的画,就是说数据应当不会被破坏。隔离性(Isolated):事务应该允许多个用户操作同一个数据,一个用户的操作不会和其他用户的操作相混淆。因此,事务必须是相互隔离的,防止并发读写同一个数据的情况发生。持久性(Durable):一旦事务完成,事务的结果应该持久化,这样不管什么样的系统崩溃,他们都将幸免于难。通常把事务的结果保存在数据库或其他形式的持久化存储设备中。在电影票的例子中,当任何一步失败时,事务能通过撤销所有步骤的结果来保

4、证原子性。原子性维护了一致性,因为它确保系统中的数据永远不处于一种不一致的部分完成状态。隔离性也维护了一致性,因为当你仍处于买票过程中,它防止另一个并发的事务抢了你的位子。最后,结果将被持久化,因为他们将提交到某个持久化存储中。当系统崩溃或发生其他灾难时,你就不用担心事务的结果会丢失。nSpring的事务管理器Spring没有直接管理事务,但它有很多的事务管理器,下面是事务管理器列表:事务管理器实现目标org.springframework.jdbc.datasource.DataSourceTransactionManager在单一的JDBC DataSource中管理事务org.sprin

5、gframework. orm.hibernate.HibernateTransactionManager当持久化机制是Hibernate时,用它来管理事务org.springframework.orm.jdo.JdoTransactionManager当JDO用作持久化时,用它来管理事务org.springframework.transaction.jta.JtaTransactionManager使用一个JTA(Java Transaction API)实现来管理事务。在一个事务跨越多个资源时必须使用org.springframework.orm.ojb.PersistenceBroker

6、TransactionManager当Apache的OJB(Object Relational Bridge)用作持久化时,用它来管理事务。每一种事务管理器都充当了对特定平台的事务实现的代理,以下是Spring的事务管理器:PlatformTransactionManagerDataSourceTransactionManagerJDOTransactionManagerJTATransactionManagerHibernateTransactionManagerPersistenceBrokerTransactionManagerJDBCHibernateJDOOJBJTAJDBC事务如果

7、直接使用JDBC作为应用持久化机制,DataSourceTransactionManager将为你处理事务边界。可以用下面的XML把它置入到应用的上下文定义中:在某后,DataSourceTransactionManager通过调用从DataSource得到的对象来管理事务,例如通过调用Connection的commit()方法来提交或rollback方法来回滚。 定义在配置文件某个地方的javax.sql.DataSource BeanHiberante事务如果你的持久层是用Hibernate来实现的,那你就会用到HibernateTransactionManager,我们可以通过下面的方式

8、来声明它:HibernateTransactionManager 把事务委托给一个从Hibernate Session中取得的对象。当一个事务成功完成时, HibernateTransactionManager 将调用Transaction对象的commit()方法提交或rollback()方法回滚。 定义在配置文件某个地方的Hibernate的SessionFactoryJDO事务可能你不喜欢JDBC和Hibernate,决定使用JDO(Java Data Object)实现应用的持久层。这样的话,应该选择的事务管理器是,那你就会用到JdoTransactionManager,我们可以通过下

9、面的方式来声明它:使用JdoTransactionManager,你需要将实例绑定到persistenceManagerFactory属性中。在幕后, JdoTransactionManager和一个从JDO持久化管理器中得到的事务对象一起工作,在一个事务成功结束后调用commit()方法提交或rollback()方法回滚。 JTA事务如果你的事务是跨越多种事务资源的(比如:两个或者更多的数据库),你就需要使用JtaTransactionManager:JtaTransactionManager把事务管理的责任委托给一个JTA的实现。JTA定义了一套标准的APT,可以协调应用和一个或多个数据源

10、之间的事务。其中transactionManagerName属性指定了一个JTA事务管理器,这个事务管理器是通过JNDI找到的。JtaTransactionManager和及对象一起工作,并将事务管理的责任委托给这些对象。一个成功的事务通过调用UserTransaction mit()方法提交,调用UserTransaction.rollback()方法回滚。 java:/TransactionManager 在Spring中编写事务n在你的代码中添加事务的一种方法就是使用Spring的TransactionTemplate类,永程序添加事务边界。就像其他Spring的模板类一样,Transa

11、ctionTemplate利用一套回调机制。如我们前面讲过的在线注册课程系统中,在enrolStudentInCourse()方法中进行事务控制:public void enrolStudentInCourse() transactionTemplate.execute( new TransactionCallback() public Object doInTransaction( TransactionStatus ts ) try /do stuff catch(Exception e) ts.setRollbackOnly(); return null; );在doIntransact

12、ion()方法中进行如果成功,事务被提交调用setRollBackOnly回滚你从实现TransactionCallback接口开始。由于TransactionCallback只有一个方法要实现,通常,最简单的做法就是把它实现成一个匿名内联类,就像上面的示例一样,把你要在事务上下文运行的代码放在doInTransaction()方法里。调用TransactionTemplate实例的execute()方法将执行包含在TransactionCallback实例的代码。如果你的代码碰到一个问题,调用TransactionStatus对象的setRollbackOnly()方法将使事务回滚。否则,如

13、果doInTransaction()方法正常返回,事务将被提交。TransactionTemplate实例从哪里来的?如下所示,它将被注入到CourseServiceImpl中: 注意transactionTemplate对象有一个transactionManager属性。在幕后,TransactionTemplate使用PlatFormTransactionManager的一个实现来处理特定平台的事务管理的细节。这里我们置入了一个名为transactionManager的对象的引用,它可以是我们上面讲到的Spring事务管理器中任何PlatformTransactionManager的实现。

14、当你希望完全控制事务的边界时,程序控制的事务是不错的。但是,正如你在enrollStudentInCourse()方法中看到的,他们有点像入侵者,你得改变enrollStudentInCourse()的代码,并且使用Spring的特定类-来使用Spring所支持的程序控制的事务。通常,你得事务需求并没有要求在事务的边界上进行如此精确的控制。这就是我们一般选择在应用代码之外声明事务的原因。下面我们学习声明式事务管理。声明式事务 Spring对声明式事务管理得支持是通过它的AOP框架实现的。这样做是非常自然的,因为事务是系统级的,凌驾于应用的主要功能之上的。你可以把Spring的事务想成是一个切面

15、,“包裹”着一个方法。 要在Spring使用声明式事务,你得用TransactionProxyFactoryBean。这个proxy factory对象类似于我们以前学习过得ProxyFactoryBean,只不过它的目的是将方法包装在事务上下文中。下面我们展示如何声明一个TransactionProxyFactoryBean: BusinessManager.CourseService 命名规范:被继承得目标对象名字“Target”代理所实现的接口被代理的对象事务管理器事务的属性源 上面的示例中,但应用系统从应用上下文里请求一个courserService时,它将得到一个被Transacti

16、onProxyFactoryBean包裹的代理实例,而原来的courseService对象应被重新命名(可以取任何名字,但推荐根据规范命名,在原来的名字基础上加”Target”字符) ,否则对象的id就会冲突。 TransactionProxyFactoryBean除了它的目标对象之外还有两个合作者。为了明确事务的上下文,transactionManager属性指定了一个PlatformTransactionManager的实例,它可以是Spring事务管理器的任何一个实现。 而transactionAttributeSource属性包含了一个指向TransactionAttributeSou

17、rce对象的引用。为了理解事务属性源是如何工作的,必须首先理解事务属性。所以,让我们来仔细看看事务属性是如何定义的。n理解事务属性在Spring里,事务属性是对事务策略如何应用到方法的描述。这个描述包括下了一个或多个参数:传播行为隔离级别只读提示事务超时间隔传播行为传播行为定义了关于客户端和被调用方法的事务边界。Spring定义了7种截然不同的传播行为,见下表所列:传播行为意义PROPAGATION_MANDTORY表示方法必须运行在一个事务中。如果事务不存在,将抛出一个异常。PROPAGATION_NESTED表示如果当前已经存在一个事务,则该方法应当运行在一个嵌套的事务中。被嵌套的事务可以

18、从当前事务中单独地提交或回滚。如果当前事务不存在,那么他看起来就和PROPAGATION_REQUIRED没有两样。请注意各厂商对于这种传播行为地支持是参差不齐地。请参考资源管理器的文档,确定他们是否支持嵌套的事务。PROPAGATION_NEVER表示当前的方法不应该运行在一个事务上下文中。如果当前存在一个事务,则会抛出一个异常。PROPAGATION_NOT_SUPPORTED表示该方法不应在事务中运行。如果一个现有的事务正在进行中,他将在该方法的运行期间被挂起。如果使用JTATransactionManager的话,需要访问TransactionManager。传播规则回答了一个问题,就

19、是新的事务是否要被启动或是被挂起,或者方法是否要在事务环境中运行。传播行为意义PROPAGATION_REQUIRED表示当前方法必须运行在一个事务中。如果一个现有的事务正在进行中,该方法将运行在这个事务中。否则的话,就要开始一个新的事务。PROPAGATION_REQUIRES_NEW表示当前方法必须运行在它自己的事务里。它将启动一个新的事务。如果一个现有事务在运行的话,将在这个方法运行期间被挂起。如果使用JTATransactionManager,则需要访问TransactionManager。PROPAGATION_SUPPORTS表示当前方法不需要事务处理环境,但如果有一个事务已经在运

20、行的话,这个方法也可以在这个事务里运行。隔离级别在一个典型的应用中,多个事务并发运行,经常会操作同一个数据来完成他们的任务。并发,虽然是必须的,但会导致以下问题:脏读(Dirty read)-脏读发生在一个事务读取了被另外一个事务改写但还没未提交的数据时。如果这些改变在稍后被回滚,那么第一个事务读取的数据就是无效的不可重复读(Nonrepeatable read)-不可重复读发生在一个事务执行相同的查询两次或两次以上,但每一次查询结果都不同时。这通常是由于另一个并发事务在两次查询之间更新了数据。幻读(Phantom read)-幻读和不可重复读相似。当一个事务(T1)读取几行记录后,另一个并发

21、事务(T2)插入一些记录,幻读就发生了。在后来的查询中,第一个事务(T1)就会发现,有一些原来没有的额外的记录。在理想状态下,事务要完全相互隔离,以防止这些问题发生。然而,完全隔离会影响性能,因为隔离经常牵扯到锁定在数据库中的记录(有时是锁定完整的数据表)。侵占性的锁定会阻碍并发,要求事务互相等待来完成工作。应该认识到完全隔离会影响性能,并且不是所有的应用都需要完全隔离,有时应用需要在事务隔离上有些弹性。因此就有好几个隔离级别,见下表:ISOLATION_READ_UNCOMMITTED是最高的隔离级别,但是事务的隔离程度也是最低的,事务对脏读、幻读、不可重复读是开方的在另一个极端,ISOLA

22、TION_SERIALIZATION防止任何形式的隔离问题,但效率最低。隔离级别含义ISOLATION_DEFAULT使用后端数据库默认的隔离级别ISOLATION_BEAD_UNCOMMITTED允许你读取还未提交的改变了的数据。可能导致脏读、幻读、不可重复读。ISOLATION_BEAD_COMMITTED允许在并发事务已经提交后读取,可防止脏读,但幻读和不可重复读仍可能发生。ISOLATION_REPEATABLE_READ对相同字段的多次读取的结果是一致的,除非数据被事务本身改变。可防止脏读和不可重复读,但幻读仍可能发生。ISOLATION_SERIALIZABLE完全服从ACID的隔

23、离级别,确保不发生脏读、不可重复读、幻读。这在所有隔离级别中也是最慢的,因为他是典型的通过完全锁定在事务中设计的数据表来完成的。只读提示如果一个事务只对后端数据库执行读操作,数据库就可能利用事务只读的特性,使用某些优化措施。只读的优化措施是在事务启动时由后端数据库实施的,所以,只有将那些具有可能启动新事务的传播行为的方法的事务标记成只读才有意义(PROPAGATION_REQUIRED,PROPAGATION_REQUIRES_NEW和PROPAGATION_NESTED)。此外,如果你使用Hibernate作为持久化机制,声明一个只读事务将使Hibernate的flash模式设置为FLUSH

24、_NEVER,这就告诉Hibernate避免和数据库进行不必要的对象同步,将所有更新延迟到事务的结束。事务超时最后,在事务中你可能选择设置的另一个属性就是超时。假设你的事务在预料之外长时间运行,因为事务可能涉及对后端数据库的锁定,长时间运行的事务会不必要的占用数据库资源。与其等它结束,不如声明一个事务,在特定秒数后自动回滚。因为在事务启动的时候,超时的时钟就开始滴答响了,所以,只有将那些具有可能启动新事务的传播行为的方法的事务设置超时才有意义(PROPAGATION_REQUIRED,PROPAGATION_REQUIRES_NEW和PROPAGATION_NESTED)。n声明一个简单的事务

25、策略在本章的开始部分,我们展示了如为CourseServiceImpl声明一个TransactionProxyFactoryBean ,其中有一个属性被设置成一个TransactionAttributeSource的实例。 TransactionAttributeSource通过如下接口定义:下面我们在配置文件中定义transactionAttributeSource对象:我们通过MatchAlwaysTransactionAttributeSource声明了一个transactionAttributeSource对象,所有被TransactionProxyFactoryBean的目标类代理的

26、方法都被执行在一个事务环境中了。public interface TransactionAttributeSource public TransactionAttribute getTransactionAttribute( java.long.reflect.Method.method, java.long.Class targetClass); 在上面实例中,并没有指定哪个方法是事务性的,或者要应用哪个事务策略。 MatchAlwaysTransactionAttributeSource是最简单的TransactionAttributeSource的实现。每次它的getTransactio

27、nAttribute()方法被调用时,它总是简单的返回相同的TransactionAttribute,而不管这个事务中包装了哪个方法(默认是PROPAGATION_REQUIRED和ISOLATION_DEFAULT)。那就是MatchAlwaysTransactionAttributeSource的“永远匹配(match always)”部分在起作用。n改变默认事务属性MatchAlwaysTransactionAttributeSource的getTransactionAttribute()方法总是返回带PROPAGATION_REQUIRED/ISOLATION_DEFAULT策略的事务

28、属性,如果你希望返回一个和默认值不同的TransactionAttribute,可以在transactionAttribute属性中置入另一个TransactionAttribute。如下面的配置: property name=“propagationBehaviorName” PROPAGATION_REQUIRES_NEW ISOLATION_REPEATABLE_READ 定义一个定制事务对象,通过propagationBehaviorName属性设置传播行为, isolationLevelName属性设置了隔离级别将定制事务对象帮定到transactionAttribute属性上,覆盖

29、了默认事务属性n尽管你可以改变MatchAlwaysTransactionAttributeSource的事务属性参数,当它总是返回相同的事务属性,应用到所有的方法。当你需要对不同的方法应用不同的事务策略,应该怎么做呢?通过方法名声明事务nNameMatchTransactionAttributeSource我们还是以CourseService为例,现在我们要声明enrollStudentInCourse()方法具有”requires new”的传播行为,应该怎样做呢?见下面的配置: PROPAGATION_REQUIRES_NEW 这个Bean将被置入到TransactionProxyBea

30、n的transactionAttributeSource属性中,示例。NameMatchTransactionAttributeSource的properties属性把方法映射到事务属性描述器上,事务属性描述器有以下几种形式:在上面的例子中,只指定了传播行为。但正如你所看到的,事务属性的很多其他参数都可以在事务属性描述器中定义。下面我们学习一下事务属性描述器的其他部分。PROPAGATION, ISOLATION, readonly, -Exceptions, +Exceptions传播行为隔离级别(可选)是只读事务吗?(可选)回滚规则(可选)指定事务隔离级别如果我们希望enrollStude

31、ntCourse()方法不当有”requires new”的传播行为,还要有”repeatable read”的隔离级别,我们所有做的就是ISOLATION_REPEATABLE_READ加到事务属性中,和传播行为用逗号分开: PROPAGATION_REQUIRES_NEW, ISOLATION_REPEATABLE_READ 使用只读事务如果你要将事务声明为只读的,只要在事务属性列表中添加readOnly即可。例如,声明getCompletedCourse方法被包装在一个为只读访问而优化的事务中,配置如下: PROPAGATION_REQUIRES_NEW, ISOLATION_REPEA

32、TABLE_READ,readOnly 指定回滚规则当事务运行过程中抛出异常时,事务可以被声明为回滚或者不回滚。默认情况下,发生运行时间异常时,事务将被回滚;发生受查异常(checked exception)时,不回滚。然而,你也可以指定事务在特定的受查异常时也回滚。如,当抛出CourseException时,要让事务总是回滚,我们只要把事务属性修改成如下所示: PROPAGATION_REQUIRES_NEW, ISOLATION_REPEATABLE_READ, -CourseException 负号(-)表示当异常发生时,将触发回滚正号(+)表示当异常发生时,事务仍可提交使用通配符匹配你

33、还可以使用通配符匹配这个模式的多个方法,声明事务策略。如我们要把”supports”传播行为应用到所有方法名以”get”开头的方法,如下所示: PROPAGATION_SUPPORTS n名称匹配事务的捷径前面讲到的事务,我们都是使用NameMatchTransactionAttributeSource先定义一个Bean,将其命名为transactionAttributeSource,然后将其注入到TransactionProxyFactoryBean的transactionAttributeSource属性中,这种方法虽然能很好的工作,但这里还有一种更简单轻巧的方法。TransactionP

34、roxyFactoryBean还有一个transactionAttributes属性,与其把NameMatchTransactionAttributeSource对象置入到这个属性,不如直接把事务属性绑定到transactionAttributes属性: PROPAGATION_REQUIRES_NEW 这种设置的功效和使用NameMatchTransactionAttributeSource是一样的。在幕后,TransactionProxyFactoryBean会创建它自己的NameMatchTransactionAttributeSource,并把这些设置在transactionAttri

35、butes属性的上的值传递到NameMatchTransactionAttributeSource的setProperties()方法中。用元数据声明事务n当前java开发者有两种可用的元数据的实现:Jakarta Commons Attribute和JSR-175。JSR-175的元数据支持已作为Java5的一部分被发布,成为java的元数据规范。在Spring1.0发布的时候,Java5还是一个beta版本,所以,Spring1.x版本仅支持Jakarta Commons Attribute的元数据的实现。n用元数据来书写事务属性为了让TransactionProxyFactoryBean

36、能够从元数据中检索事务属性,需要将它的transactionAttributeSource设置成AttributeTransactionAttributeSource,如下所示:注意,我们在这个事务属性源的构造函数中置入了一个名为attributesImpl的对象的引用。这个attributesImpl对象将被事务属性源使用,和底层的元数据实现配合。 n用Commons Attribute声明事务Jakarta Commons Attribute是最早在Java中实现元数据的方法之一。声明一个属性的实现在上面的示例中,我们声明AttributeTransactionAttributeSourc

37、e对象时,在构造方法中传递了一个attributesImpl对象的引用。现在我们利用Commons Attribute作为元数据的实现来检索事务属性:通过把CommonsAttribute作为元数据实现置入AttributeTransactionAttributeSource中。Spring将会寻找作为元数据标签加在事务方法上的事务属性。因此,下步要做的事情就是在哪些方法上贴上事务属性标签。 给事务方法加上标签Jakarta Commons Attribute通过在类或方法前面的注释中放置doclet标签,把自己应用到类或方法中。这些doclet标签有以下几种形式:假如,enrollStude

38、ntInCourse方法需要在事务上下文中执行,我们只需要用DefaultTransactionAttribute类贴上标签,并且把propagationBehaviorName参数设置为PROPAGATION_REQUIRED。/* * attribute-name(“arg1”,property=“arg2” */属性的名称设置一个属性的参数构造方法的参数/* * ( propagationBehaviorName=“PROPAGATION_REQUIRED”) */public void enrollStudentInCourse() .注意,当把它作为一个属性使用的时候,必须使用Def

39、aultTransactionAttribute的完整类名。因为在Commins Attributes对CourseServiceImpl完成预编译之后,它将重写CourseServiceImpl来引用DefaultTransactionAttribute的实例。除非你指定包名,否则在编译被生成的CourseServiceImpl类时将发生编译错误。另一种做法是,你可以选择导入整个包,这样就能直接使用类名了。但要小心你的IDE不会自动删除这个包,因为你的IDE很可能认为这些属性包是没有必要导入的,就会自动删除他们。通过在类级别放置事务标签,你能够指定应用到这个类中所有没有贴标签的方法的事务属性

40、。如:/* * ( propagationBehaviorName=“PROPAGATION_REQUIRED”) */public class CourseServiceImpl implements CourseService .Jakarta Commons Attributes背后的魔法就是预编译,他能把代码中doclet标签解析出来,然后重写你的类,把元数据嵌入到代码中。我们需要使用Ant来做预编译工作,你需要下载一下文件并把他们放在$ANT_HOME/lib目录下面:下一步,你需要在build.xml文件中加入一下几行,把预编译程序任务加载到Ant里:有关Ant的使用,我们在后面的

41、项目中将详细讲解。修剪事务声明 到目前为止,你已经选择了TransactionAttributeSource,把你的服务层事务声明为事务性的。我们再看一下声明式事务一节开头部分的配置配件,你就会发现,所有的服务对象都用同样的方法定义,并设定了相同的事务管理器和相同的事务属性源。如果能完全消除重复的TransactionProxyFactoryBean实例,那不是更好吗?Spring提供两种方法抗击这个繁复的XML:nBean继承nAOP自动代理n从父TransactionProxyFactoryBean继承简化事务和服务对象声明的一种方法是使用Spring对父bean的支持。使用标签的pare

42、nt属性,就能够指定一个bean成为其他bean的孩子,继承父bean的属性。使用Bean继承来缩减包含多重TransactionProxyFactoryBean声明的XML,开始于在上下文定义中添加一个TransactionProxyFactoryBean的abstract声明: 首先,它的lazy-init属性是设置为true的。应用上下文通常在启动的时候实例化所有singleton bean。既然我们的应用仅仅使用astractTxDefinition的子bean,而不会直接使用abstractTxDefinition,那么我们就不希望容器去初始化一个我们从来不用的bean。Lazy-i

43、nit属性告诉容器不要创建bean,实际上,lazy-init就是把这个bean变成抽象的。Target属性奇怪的消逝了。我们将在子bean里设置这个属性。下面,我们创建子bean courseService: BusinessManager.CourseService 现在,我们不用再完整的为每一个Bean都定义一个TransactionProxyFactoryBean,现在想象一下,如果我们的系统中有上百个、甚至上千个服务bean需要被事务化,这会给我们节省大量的繁琐的配置工作。下面,我们再来看一下如何使用AOP自动代理来完全消除对TransactionProxyFactoryBean的需

44、要n自动代理事务首先,就像要做任何自动通知(auto-advising)一样,你需要声明一个bean,成为DefaultAdvisorAutoProxyCreator的实例:DefaultAdvisorAutoProxyCreator将在应用上下文中遍历advisor,自动用他们来代理匹配advisor的pointcut的所有bean。对于事务,应该使用的advisor是TransactionAttributeSourceAdvisor: 关于拦截器,它通过一个构造参数置入到TransactionAttributeSourceAdvisor。它由TransactionInterceptor类实

45、现并像下面那样被置入到应用中:下面我们为自动代理选择一个属性源: PROPAGATION_SUPPORTS 使用这种方式,所有名字以“get”开始的方法,将被一个“supports”的事务传播行为代理。可能这正式你所希望的,但也可能不是。 DefaultAdvisorAutoProxyCreator将试图代理在应用上下文所有bean的全部方法,在任何bean中如果有名称以“get”开头的方法,它就会被代理。但使用自动代理时,对于事务属性源的一个更好的选择是MethodMapTransactionAtrributeSource。这个事务属性源让你指定需要事务化的完整类名称和方法名。例如: PRO

46、PAGATION_SUPPORTS 用这种方式使用MethodMapTransactionAttributeSource,得明确只有CourseServiceImpl的”get”方法是有“supports”的事务传播行为的。要在其他类的方法中添加事务行为,你需要在方法映射中加元素。现在我们最后要做的一件事情就是删除所有TransactionProxyFactoryBean的实例,并把服务层bean重命名回他们原来正确的名称,如,CourseServiceTarget改成courseService。当用自动代理时,事务属性源的一个更好的选择是AttributeTransactionAttributeSource, AttributeTransactionAttributeSource把事务属性从元数据中取出来,而这些元数据是直接放在要初始化的方法的代码中的。这就意味着,如果你使用AttributeTransactionAttributeSource作为属性源,并同时使用自动代理的话,使方法事务化或非事务化,只不过是添加合适的元数据到方法而已。

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 资格认证/考试 > 自考

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号