Spring 声明式事物配置文件解析
来源:互联网 发布:sql向表中更改字段 编辑:程序博客网 时间:2024/05/21 09:26
11.5.5 <tx:advice/>settings
这节总结了可以使用<tx:advice>标签指定的不同事物设置。默认的<tx:advice/>设置是:
- 传播设置是必须的
- 隔离级别是默认的
- 事物是读/写的
- 事物超时是底层事物系统的默认超时,或者超时不支持即为空
- 任何运行期异常触发回滚,并且任何检查型异常不触发
你可以变更这些默认的设置;<tx:method/>
标签的不同属性嵌入在<tx:advice/>
之内,并且<tx:attributes/>
标签总结如下:
Table 11.1. <tx:method/> settings
属性 是否必须 默认 描述
name 是 事物属性关联的方法名。通配符*可用于关联大量方法的相同事物属性设置;例如,get*,handle*,on*Event,等等
propagation 否 REQUIRED 事物传播行为
isolation 否 DEFAULT 事物隔离级别
timeout 否 -1 事物超时时间(以秒为单位)
read-only 否 这个事物是否只读?
rollback-for 否 异常触发的回滚:逗号隔开。例如,com.foo.MyBusinessException,ServletException.
no-rollback-for 否 异常不触发回滚:逗号隔开。例如,com.foo.MyBusinessException,ServletException.
11.5.6 使用@Transactional
除了使用基于XML的声明方式配置事物外,你可以使用基于注解的方式。在Java源代码中声明式语义使得声明与受影响的代码更近。不当的结合没有太多的危险,因为用于事物的代码将总是以任何方式部署。
下面的例子是使用@Transaction注解的例子。考虑下面的类定义:
// the service class that we want to make transactional@Transactionalpublic class DefaultFooService implements FooService { Foo getFoo(String fooName); Foo getFoo(String fooName, String barName); void insertFoo(Foo foo); void updateFoo(Foo foo);}
当上述的POJO被定义为Spring IoC容器中的一个bean时,可以通过在XML配置中仅仅添加一行使得这个bean是事物性的。
<!-- from the file context.xml --><?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- this is the service object that we want to make transactional --> <bean id="fooService" class="x.y.service.DefaultFooService"/> <!-- enable the configuration of transactional behavior based on annotations --> <tx:annotation-driven transaction-manager="txManager"/><!-- a PlatformTransactionManager is still required --> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- (this dependency is defined somewhere else) --> <property name="dataSource" ref="dataSource"/> </bean> <!-- other <bean/> definitions here --></beans>
注意:如果你想要封装的PlatformTransactionManager
的bean名有名字transactionManager
,那么你可以标签<tx:annotation-driven/>
的transaction-manager
元素。如果你想依赖注入的 PlatformTransactionManager
bean有其他名字,那就必须直接使用transaction-manager
元素,如同前面的例子一样。
@EnableTransactionManagement
注解提供了基于Java配置相同的注解。仅仅是将其添加到@Configuration
类。
@Transactional
注解可以放在一个接口定义前,一个接口的方法前,一个定义类,或者类的public方法前。然而,仅仅通过@Transactional
注解不能激发事物行为。@Transactional
仅仅是可供运行底层(需要@Transactional提醒的
)消耗的元数据,并且可以使用元数据配置有事物行为的合适的bean。在前面的例子中,<tx:annotation-driven/>
元素可在事物行为上转换。
注意:Spring推荐使用@Transactional
仅注解具体的类(和具体类的方法),而不是注解接口。虽然可以使用@Transactional直接注解在接口上或接口方法上,但是这仅在你想基于接口代理的时候使用才有效。实际上Java注解不从接口继承,意味着如果你想使用基于类的代理(proxy-target-class="true"
)或者基本封装方面(mode="aspectj"
),那么事物设置不会被代理和封装底层识别,并且对象不封装在事物代理中,这样明显很糟糕。
注意:在代理模式中(默认的),仅仅通过代理的外部方法调用被拦截。这意味着自调用,实际上,目标对象内的一个方法调用了目标对象的另一个方法,将不会在运行期导致一个确切的事物,即使那个方法被@Transaction标示。
如果希望自调用封装了事物,考虑AspectJ模式的使用。在这种情况下,首先将不会有一个代理。而是将目标对象编织封装(即修改其字节码),这样将@Transaction转为任何种类方法的运行期行为。
table 11.2 注解驱动的事物设置
XML 属性 注解属性 默认 描述
transaction-manager N/A transactionManager transaction manager 使用的名字。如果事物管理的名字不是transactionManager 则是必须的,
如同上面的例子
mode mode proxy 默认模式“proxy”处理注解的要被代理的beans,使用Spring AOP框架(遵循代理语义,如同上面讨论的,应用于仅通过代理的方法调用)。可选的模式“aspectj”使用Spring AspectJ事物方面编织受影响的类,并修改目标类字节码应用于任何种类的方法调用上。AspectJ编织需要类路径的spring-aspectj.jar,也需要加载时编织(或者编译时编织)
proxy-target-class proxyTargetClass false 仅仅用于代理模式。为@Transaction注解的类控制创建哪种类型的事物代理。如果proxy-target-class属性设置为true,那么创建基于类的代理。如果这个属性是false,或者忽略了这个属性,那么创建基于代理的标准JDK接口。
order order Order.LOWEST_PRECEDENCE 定义应用于@Transaction注解beans的事物建议顺序。没有指定顺序意味着AOP子系统决定了advice的顺序。
注意:proxy-target-class 决定了为@Transactional注解的类创建哪种类型的事物代理。如果此元素设置为true,创建基于类的代理。如果这个属性设置为false,或者如果忽略这个属性,创建基于接口的标准JDK代理
注意:
@EnableTransactionManagement
和<tx:annotation-driven/>
仅寻找在相同应用程序上定义的@Transactional
的bean。意味着,如果你为了DispatchServlet将注解驱动放置于一个WebApplicationContext中,仅在你的控制器中检核@Transaction的bean,而不是在你的Service bean中。
当评估一个方法的事物设置时,最低层的衍生位置优先。在下面的例子中,使用read-only事物在类级别注解
,但是了同一个类的updateFoo(Foo foo)方法上的DefaultFooService
@Transactional
注解覆盖了类级别的注解。
@Transactional(readOnly = true)public class DefaultFooService implements FooService { public Foo getFoo(String fooName) { // do something } // these settings have precedence for this method @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW) public void updateFoo(Foo foo) { // do something }}
@Transactional settings
@Transactional
注解是元数据,指定的类,接口,或方法必须有事物语义;例如,当这个方法调用时开启一个新的read-only事物,挂起任何其他的事物。默认的@Transaction设置如下:
传递性设置时
PROPAGATION_REQUIRED.
隔离性设置是
ISOLATION_DEFAULT.
事物是读/写的
事物超时默认是底层事物系统默认的超时,或者不支持的话 默认为null
任何运行异常触发回滚,但检查性异常不会
可以改变这些默认的设置;@transaction注解的不同属性总结如下:
Table 11.3 @
属性 类型 描述
value String 可选的限定符指定要使用的事物管理器
propagation enum:Propagation 可选的传递性设置
isolation enum:Isolation 可选的隔离级别
readOnly boolean 读/写 或者read-only事物
timeout int(单位秒) 事物超时
rollbackFor Class对象数组,必须继承Throwable 异常类的可选数组,必须引起回滚
rollbackForClassName 类名数组。类必须继承Throwable 异常类名的可选数组,必须引起回滚
noRollbackFor 类对象数组,继承Throwable 异常类可选数组,不必引发回滚
noRollbackForClassName Sring 类名数组,必须继承Throwable 异常类的可选数组,不必引发回滚
当前不能直接控制事物名,名字将在事物监视器中显示。如果合适,(例如,WebLogic的事物监视器),和日志输出。对于声明式事物,事物名总是全限定类名+“。”+事物建议的类的方法名。例如,如果BusinessService
类的handlePayment(..)
方法开启了一个事物,事物名将是:com.foo.BusinessService.handlePayment
.
@Transactional多事物管理器
大多数应用程序只需要一个单一的事物管理器,但是了可能出现这样的情形,你想在一个单一应用程序中使用多个独立的事物管理器。@Transactional
注解的value属性可用于指定要使用的PlatformTransactionManager
的标示。这个可以是bean名称或者事物管理bean的限定名称。例如,使用限定符号,下面的Java code:
public class TransactionalService { @Transactional("order") public void setSomething(String name) { ... } @Transactional("account") public void doSomething() { ... }}
在应用程序上下文中可以联合使用下面的事物管理器bean声明
tx:annotation-driven/> <bean id="transactionManager1" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> ... <qualifier value="order"/> </bean> <bean id="transactionManager2" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> ... <qualifier value="account"/> </bean>
在这个例子中,TransactionalService
的两个方法将在不同的事物管理器下运行,分别由order和account限定名区分。默认的<tx:annotation-driven>
目标bean名称transactionManager
仍然会被使用,如果没有发现指定的PlatformTransactionManager。
通用的快捷的注解
如果发现在不同的方法上重复使用@Transactional
相同的属性。那么Spring’s meta-annotation support允许你为你指定的使用情况定义通用便捷的注解。例如,定义下面的注解:
@Target({ElementType.METHOD, ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Transactional("order")public @interface OrderTx {}@Target({ElementType.METHOD, ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Transactional("account")public @interface AccountTx {}
这样允许我们这样写前面的额例子:
public class TransactionalService { @OrderTx public void setSomething(String name) { ... } @AccountTx public void doSomething() { ... }}
这里虽然使用语法定义了事物管理器限定符,但是了也包括了传播性行为,回滚规则,超时等
11.5.7 Transaction propagation 事物传递性
这部分描述了Spring中的事物传递性的一些语法。记住这里不是讲解事物传递属性,而是详细介绍事物传递语法。
在Spring管理的事物中,注意物理和逻辑事物的不同,和这些传递设置如何应用在这些不同之处。
Required
PROPAGATION_REQUIRED
当传播设置为PROPAGATION_REQUIRED
,将为应用这些设置的方法创建逻辑事物范围。每个这样的逻辑事物范围可以分别指定rollback-only状态,其外部的事物范围与内部的事物范围会不干扰。当然了,在标准PROPAGATION_REQUIRED
行为情况下,所有这些范围将被映射为相同的物理事物。这样一个内部事物范围的rollback-only标示设置确实影响了外部事物的提交。
然而,在内部事物范围设置为rollback-only标示的情况下,外部事物不能自己决定其回滚,并且回滚(由内部事物触发的范围)不可预测。此时抛出相应的UnexpectedRollbackException
。这是可以预料的行为,这样事物调用者从来不会误导,假设执行了提交,当其不是真正的提交的时候。如果一个内部事物(外部事物注意不到)标示为一个read-only的事物,外部调用仍旧调用提交。外部调用者需要接受一个UnexpectedRollbackException
来清晰的指定执行的回调。
RequiresNew
PROPAGATION_REQUIRES_NEW
PROPAGATION_REQUIRES_NEW相比较于PROPAGATION_REQUIRED
,对于每个受影响的事物范围使用一个完全独立的事物。在那个情况下,指定的物理事物是不同的并且可以独立的提交或回滚,即外部事物不会受内部事物回滚状态的影响。
Nested(嵌套)
PROPAGATION_NESTED
使用单一物理事物,其可以回滚到多个savepoints。这样局部的回滚允许一个内部事物范围触发器范围内的回滚,同时,外部事物能够继续忽略物理事物的一些操作,比如已经执行的回滚。这个设置一般映射到JDBC的savepoints,所以了只有在JDBC的资源事物中有效。
11.5.8 Advising transactional operations
假如你想执行事务性和基本设置文件的advice。那如何在<tx:annotation-driven/>
上下文中起作用了?
当你调用updateFoo(Foo)
方法时,你想看见如下的动作:
- 配置设置文件方面启动
- 事物建议执行
- 建议对象方法的执行
- 事物提交
- 设置文件方面记录整个事物方法调用的确切期间
下面是一个简单的设置文件方面的例子。advice的顺序由Ordered接口控制。
package x.y;import org.aspectj.lang.ProceedingJoinPoint;import org.springframework.util.StopWatch;import org.springframework.core.Ordered;public class SimpleProfiler implements Ordered { private int order; // allows us to control the ordering of advice public int getOrder() { return this.order; } public void setOrder(int order) { this.order = order; } // this method is the around advice public Object profile(ProceedingJoinPoint call) throws Throwable { Object returnValue; StopWatch clock = new StopWatch(getClass().getName()); try { clock.start(call.toShortString()); returnValue = call.proceed(); } finally { clock.stop(); System.out.println(clock.prettyPrint()); } return returnValue; }}
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="fooService" class="x.y.service.DefaultFooService"/> <!-- this is the aspect --> <bean id="profiler" class="x.y.SimpleProfiler"> <!-- execute before the transactional advice (hence the lower order number) --> <property name="order" value="1"/> </bean> <tx:annotation-driven transaction-manager="txManager" order="200"/> <aop:config> <!-- this advice will execute around the transactional advice --> <aop:aspect id="profilingAspect" ref="profiler"> <aop:pointcut id="serviceMethodWithReturnValue" expression="execution(!void x.y..Service.(..))"/> <aop:around method="profile" pointcut-ref="serviceMethodWithReturnValue"/> </aop:aspect> </aop:config> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/> <property name="url" value="jdbc:oracle:thin:@rj-t42:1521:elvis"/> <property name="username" value="scott"/> <property name="password" value="tiger"/> </bean> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean></beans>
上述配置的结果是一个fooservice bean按照预期的顺序的设置文件和事物切面。你可以按照相似方式配置其他的切面。
下面的例子显示了上述相同的配置,但是仅用了纯净的XML事物声明方式。
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="fooService" class="x.y.service.DefaultFooService"/> <!-- the profiling advice --> <bean id="profiler" class="x.y.SimpleProfiler"> <!-- execute before the transactional advice (hence the lower order number) --> <property name="order" value="1"/> </bean> <aop:config> <aop:pointcut id="entryPointMethod" expression="execution(* x.y..Service.(..))"/> <!-- will execute after the profiling advice (c.f. the order attribute) --> <aop:advisor advice-ref="txAdvice" pointcut-ref="entryPointMethod" order="2"/> <!-- order value is higher than the profiling aspect --> <aop:aspect id="profilingAspect" ref="profiler"> <aop:pointcut id="serviceMethodWithReturnValue" expression="execution(!void x.y..Service.(..))"/> <aop:around method="profile" pointcut-ref="serviceMethodWithReturnValue"/> </aop:aspect> </aop:config> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="get*" read-only="true"/> <tx:method name="*"/> </tx:attributes> </tx:advice> <!-- other <bean/> definitions such as a DataSource and a PlatformTransactionManager here --></beans>
上述配置的结果是一个fooService bean的配置文件并以那个顺序应用的事物切面。如果你想要执行的设置文件在的事物建议进去前,并在事物建议出来后,那么简单的设置设置文件 bean order属性的值,这样就比设置文件旧的值高点。
可以用相似的方式配置其他的切面。
11.5.9 使用AspectJ的@Transactional
也可以在Spring IoC容器外面通过一个AspectJ切面使用Spring框架的@Transaction。这样做,首先使用@Transaction注解你的类(通常是类中的方法),之后将与spring-aspectj.jar文件中的org.springframework.transaction.aspectj.AnnotationTransactionAspect
关联。切面必须与一个事物管理器关联。当然了,你可以使用Spring IoC的容器来考虑切面的依赖注入。配置事物管理切面最简单的方式是使用<tx:annotation-driven/>
并为aspectj指定mode属性。因为我们这里关注的是在Spring容器外部运行,所以了将显示如何程序化处理。
注意:
// construct an appropriate transaction managerDataSourceTransactionManager txManager = new DataSourceTransactionManager(getDataSource());// configure the AnnotationTransactionAspect to use it; this must be done before executing any transactional methodsAnnotationTransactionAspect.aspectOf().setTransactionManager(txManager);
注意:当使用这个切面时,必须注解实现类(或者类中的方法),而不是实现类的接口。切面遵循Java的规则,接口上的注解是不能继承的。
类上的@Transactional
为类中任何方法指定了默认的事物语法。
类中由@Transactional注解的方法重写了类注解的方法(如果有的话)。任何方法都能被注解,不管是否可见。
为使用AnnotationTransactionAspect
编织你的应用程序,要不使用AspectJ构建你的应用程序,要不使用加载时间进行编织。
- Spring 声明式事物配置文件解析
- Spring声明式事物
- spring 声明式事物
- spring AOP事物管理(声明式事物)
- Spring 声明式事物详解
- Spring声明式事物配置
- Spring 声明式事物 和 编程式事物
- spring集成hibernate声明式事物
- Spring声明式事物的配置
- Spring声明式事物的配置
- spring的声明式事物的配置
- Spring之声明式事物管理
- Spring JdbcTemplate 及其声明式事物 详解
- spring声明式事物控制的注意事项
- Spring 的声明式事物<06>
- Spring 注解方式使用声明式事物
- spring的声明式事物管理
- hiberante使用Spring声明式事物
- 学习Java类必须知道的几点
- 小甲鱼PE详解之区块描述、对齐值以及RVA详解(PE详解06)
- KKME医学搜索
- 北大POJ题库使用指南
- PPPoE拨号流程
- Spring 声明式事物配置文件解析
- 老道关于分区表的管理(三) 维护篇
- adadelta的实现
- 由一张暴利的地图获得的珍贵启示_——————_SADF3443
- 黑马程序员——IO(一)--File类、RandomAccessFile类、节点流类
- QQ列表的展开收起
- 在Linux下为PHP添加nosql--redis扩展模块
- PowerDesigner 15.1 安装步骤详细图解及破解
- 快速排序