一、annotation和XML的优缺点
Spring的annotation注入机制与XML注入机制本质上是相同的。annnotation简洁一些,遵循一些IOC。
XML配置的优缺点:
优点有:
1. XML配置方式进一步降低了耦合,使得应用更加容易扩展,即使对配置文件进一步修改也不需要工程进行修改和重新编译。
2. 在处理大的业务量的时候,用XML配置应该更加好一些。因为XML更加清晰的表明了各个对象之间的关系,各个业务类之间的调用。同时spring的相关配置也能一目了然。
当然,有人会说,用XML配置,在大的业务量时候会使得XML文件过大,不容易查看。这一点我们完全可以利用业务分解书写多个XML配置文件就可以了。
缺点有:
配置文件读取和解析需要花费一定的时间,配置文件过多的时候难以管理,无法对配置的正确性进行校验,增加了测试难度。
annotation配置的优缺点:
优点有:
1. 在class文件中,可以降低维护成本,annotation的配置机制很明显简单
2. 不需要第三方的解析工具,利用java反射技术就可以完成任务
3. 编辑期可以验证正确性,差错变得容易
4. 提高开发效率
缺点有:
1. 如果需要对于annotation进行修改,那么要重新编译整个工程
2. 业务类之间的关系不如XML配置那样容易把握。
3. 如果在程序中annotation比较多,直接影响代码质量,对于代码的简洁度有一定的影响。
有些人喜欢annotation, 这样bean的声明,注册,注入都在“刚好”的地方出现,很自然。
个人觉得xml比较好用,整体业务关系清晰,易维护。
二、Spring事务用xml配置
注释配置往往是类级别的,而xml配置则可以表现的更加灵活。是用 aop/tx 命名空间的配置更加灵活简单。
Propagation :key属性确定代理应该给哪个方法增加事务行为。这样的属性最重要的部份是传播行为。有以下选项可供使用:
PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED--Nested的事务和他的父事务是相依的,他的提交是要等和他的父事务一块提交的。
<?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:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" 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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <import resource="applicationContext.xml"/> <!-- Spring myBatis3模板配置 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="configLocation" value="classpath:/myBatis.xml" /> <!--<property name="typeAliasesPackage" value="org.snaker.engine.entity" />--> <property name="mapperLocations"> <list> <value> classpath*:com/hide168/library/*/dao/*.xml </value> <value> classpath*:com/hide168/module/*/dao/*.xml </value> <value> classpath*:com/hide168/protal/*/dao/*.xml </value> <value> classpath*:com/hide168/protal/*/*/dao/*.xml </value> </list> </property> </bean> <!-- mybatis spring sqlSessionTemplate --> <bean id="myBatisSqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg> </bean> <!-- mybatis mapper, 接口形式的访问 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.ztesoft.resmaster.module.dat.mapper"></property> <!--<property name="sqlSessionFactory" ref="myBatisSessionFactory"></property>--> <!--上面这句会导致:org.apache.commons.dbcp.SQLNestedException: Cannot load JDBC driver class '${jdbc.driver}'--> <property name="sqlSessionFactoryBeanName" value="myBatisSessionFactory"></property> </bean> <!-- 局部事务管理器,本地开发使用 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> <property name="globalRollbackOnParticipationFailure" value="false" /> </bean> <!--<tx:annotation-driven transaction-manager="myBatisTransactionManager" />--> <!-- proxy-target-class true:CGLIB代理 false:JDK代理--> <aop:aspectj-autoproxy proxy-target-class="true" /> <tx:advice id="myBatisTxAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- propagation设定事务传播级别--> <tx:method name="delete*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception"/> <tx:method name="insert*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception"/> <tx:method name="update*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception"/> <tx:method name="save*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception"/> <tx:method name="add*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception"/> <tx:method name="*" read-only="true" propagation="NOT_SUPPORTED" /> </tx:attributes> </tx:advice> <aop:config> <aop:advisor advice-ref="myBatisTxAdvice" pointcut=" execution(* com.hide168.module.*.service..*.*(..)) or execution(* com.hide168.mobile.*.service..*.*(..)) or execution(* com.hide168.protal.*.*.service..*.*(..))" /> </aop:config> <!--<aop:aspectj-autoproxy proxy-target-class="true" />--> <!-- 用于支持上传文件 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/> </beans>
这是使用注解方式时要配置的,代码中的具体的注解以及事务的传播性、隔离级别一般在service 层中配置
annotation方式配置事务:
@Transactional
(1)、这里说明一下,有的把这个注解放在类名称上面了,这样你配置的这个@Transactional 对这个类中的所有public方法都起作用
(2)、@Transactional 方法方法名上,只对这个方法有作用,同样必须是public的方法
比如这里就对这个方法定义了一个事务同时设置了很多属性:
@Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class,timeout=1,isolation=Isolation.DEFAULT)
public void saveUser(Map<String, String> map) throws Exception {
System.out.println("方法开始");
for (int i = 0; i < 500000; i++) {
System.out.println("*");
}
System.out.println("进入保存");
userDao.saveUser(map);
System.out.println("退出保存");
}