spring 的优势?
1.下降了组件之间的耦合性 ,实现了软件各层之间的解耦
2.可使用容易提供的众多服务,如事务管理,消息服务等
3.容器提供单例模式支持
4.容器提供了AOP技术,利用它很容易实现如权限拦截,运行期监控等功能
5.容器提供了众多的辅助类,能加快应用的开发
6.spring对于主流的应用框架提供了集成支持,如hibernate,JPA,Struts等
7.spring属于低侵入式设计,代码的污染极低
8.独立于各类应用服务器
9.spring的DI机制下降了业务对象替换的复杂性
10.Spring的高度开放性,并不强制应用彻底依赖于Spring,开发者能够自由选择spring的部分或所有java
什么是DI机制?
依赖注入(Dependecy Injection)和控制反转(Inversion of Control)是同一个概念,具体的讲:当某个角色
须要另一个角色协助的时候,在传统的程序设计过程当中,一般由调用者来建立被调用者的实例。但在spring中
建立被调用者的工做再也不由调用者来完成,所以称为控制反转。建立被调用者的工做由spring来完成,而后注入调用者
所以也称为依赖注入。
spring以动态灵活的方式来管理对象 , 注入的两种方式,设置注入和构造注入。
设置注入的优势:直观,天然
构造注入的优势:能够在构造器中决定依赖关系的顺序。
什么是AOP?
面向切面编程(AOP)完善spring的依赖注入(DI),面向切面编程在spring中主要表现为两个方面
1.面向切面编程提供声明式事务管理
2.spring支持用户自定义的切面
面向切面编程(aop)是对面向对象编程(oop)的补充,
面向对象编程将程序分解成各个层次的对象,面向切面编程将程序运行过程分解成各个切面。
AOP从程序运行角度考虑程序的结构,提取业务处理过程的切面,oop是静态的抽象,aop是动态的抽象,
是对应用执行过程当中的步骤进行抽象,,从而得到步骤之间的逻辑划分。
aop框架具备的两个特征:
1.各个步骤之间的良好隔离性
2.源代码无关性 spring
本文主要讨论Spring声明式事务中使用注解@Transactional的方式、原理及注意事项,主要包括如下内容:数据库
1 |
<beans xmlns="http://www.springframework.org/schema/beans" |
<!-- 事务管理器配置,单数据源事务 --> <bean id="pkgouTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="pkGouDataSource" /> </bean> <!-- 使用annotation定义事务 --> <tx:annotation-driven transaction-manager="pkgouTransactionManager" />
1> 事务注解方式: @Transactionalexpress
2> 事务传播行为介绍:编程
事务传播行为 | 说明 |
---|---|
@Transactional(propagation=Propagation.REQUIRED) | 若是有事务, 那么加入事务, 没有的话新建一个(默认状况) |
@Transactional(propagation=Propagation.NOT_SUPPORTED) | 容器不为这个方法开启事务 |
@Transactional(propagation=Propagation.REQUIRES_NEW) | 不论是否存在事务,都建立一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务 |
@Transactional(propagation=Propagation.MANDATORY) | 必须在一个已有的事务中执行,不然抛出异常 |
@Transactional(propagation=Propagation.NEVER) | 必须在一个没有的事务中执行,不然抛出异常(与Propagation.MANDATORY相反) |
@Transactional(propagation=Propagation.SUPPORTS) | 若是其余bean调用这个方法,在其余bean中声明事务,那就用事务。若是其余bean没有声明事务,那就不用事务 |
3> 事务超时设置:
@Transactional(timeout=30) //默认是30秒服务器
4> 事务隔离级别:mvc
事务隔离级别 | 说明 |
---|---|
@Transactional(isolation = Isolation.READ_UNCOMMITTED) | 读取未提交数据(会出现脏读, 不可重复读),基本不使用 |
@Transactional(isolation = Isolation.READ_COMMITTED)(SQLSERVER默认) | 读取已提交数据(会出现不可重复读和幻读) |
@Transactional(isolation = Isolation.REPEATABLE_READ) | 可重复读(会出现幻读) |
@Transactional(isolation = Isolation.SERIALIZABLE) | 串行化 |
@Transactional的属性:框架
默认状况下,数据库处于自动提交模式。每一条语句处于一个单独的事务中,在这条语句执行完毕时,若是执行成功则隐式的提交事务,若是执行失败则隐式的回滚事务。
事务管理,是一组相关的操做处于一个事务之中,所以必须关闭数据库的自动提交模式。这点,Spring会在org/springframework/jdbc/datasource/DataSourceTransactionManager.java中将底层链接的自动提交特性设置为false。oop
1 |
// switch to manual commit if necessary。 this is very expensive in some jdbc drivers, |
Spring事务管理器回滚一个事务的推荐方法是在当前事务的上下文内抛出异常。Spring事务管理器会捕捉任何未处理的异常,而后依据规则决定是否回滚抛出异常的事务。
默认配置下,Spring只有在抛出的异常为运行时unchecked异常时才回滚该事务,也就是抛出的异常为RuntimeException的子类(Errors也会致使事务回滚)。而抛出checked异常则不会致使事务回滚。
Spring也支持明确的配置在抛出哪些异常时回滚事务,包括checked异常。也能够明肯定义哪些异常抛出时不回滚事务。
还能够编程性的经过setRollbackOnly()方法来指示一个事务必须回滚,在调用完setRollbackOnly()后你所能执行的惟一操做就是回滚。post
在上一篇文章中,咱们使用了声明式事务来配置事务,使事务配置从service逻辑处理中解耦出来。但它还存在一些缺点:
1. 咱们只针对方法名的特定进行拦截,但没法利用方法签名的其它信息定位,如修饰符、返回值、方法入参、异常类型等。若是咱们须要为同名不一样参的同载方法配置不一样事务就会出问题了。
2. 事务属性的配置串虽然能包含较多信息,但配置较易出错。
针对这些问题,咱们能够基于Schema,引入tx和aop的命名空间来改进咱们的配置:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop" 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-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
<!-- 配置事务属性 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="add*" propagation="REQUIRES_NEW" /> <tx:method name="update*" propagation="REQUIRES_NEW" /> <tx:method name="delete*" propagation="REQUIRES_NEW" /> <tx:method name="*" read-only="true"/> </tx:attributes> </tx:advice> <!-- 配置事务切入点,以及把事务切入点和事务属性关联起来 --> <aop:config proxy-target-class="true"> <aop:pointcut expression="execution(* com.yc.service.*.*(..))" id="ServicePointcut" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="ServicePointcut" /> </aop:config>
这里须要特别注意的是,咱们须要在标签中将proxy-target-class配置成true,不然会出现和上一篇文章相同的错误:咱们定义的类没法转换成代理类
这里咱们经过来配置咱们的事务加强属性。在标签中,常见属性及其说明以下,其中,除了name属性是必选外,其余都是可选的:
属性 | 说明 | 默认 | 容许值 |
---|---|---|---|
name | 匹配方法名 | 必须声明,至少为* | 可以使用*通配符 |
propagation | 事务传播行为 | REQUIRED | REQUIRED,SUPPORTS和MANDATORY和REQUIRES_NEW和NOT_SUPPORTED和NEVER和NESTED |
read-only | 设置当前事务是否只读 | false | true,false |
isolation | 事务隔离级别 | DEFAULT | READ_UNCOMMITTED和READ_COMMITTED和REPEATABLE_READ和SERIALIZABLE |
timeout | 设置事务的超时时间 | -1 | 默认由顶层事务系统决定 |
rollback-for | 内容为异常名,表示当抛出这些异常时事务回滚,能够用逗号分隔配置多个 | 无默认值 | 可使用异常名称的片断进行匹配如ception等 |
no-rollback-for | 内容为异常名,表示当抛出这些异常时继续提交事务,能够用逗号分隔配置多个 | 无默认值 | 可使用异常名称的片断进行匹配如ception等。 |