Spring系列
- Spring — Spring简介、入门、配置 , IoC和DI思想
- Spring — IoC核心(基于XML)、DI核心(基于XML)
- Spring — 使用IoC和DI模拟注册案例、注解配置IoC和DI
- Spring — 静态代理、动态代理、拦截器思想
- Spring — AOP思想、AOP开发、Pointcut语法、注解配置AOP
- Spring — DAO层、Spring JDBC、Spring事务控制
- Spring — XML配置事务、注解+XML、纯注解的配置方式
- Spring整合MyBatis
- Spring Java Config — 组件注册相关注解
- Spring Java Config — 常用注解
跳转到目录
跳转到目录
在上面引出事务的代码基础上,只需要修改xml配置文件
<beans xmlns&#61;"http://www.springframework.org/schema/beans"xmlns:xsi&#61;"http://www.w3.org/2001/XMLSchema-instance"xmlns:context&#61;"http://www.springframework.org/schema/context"xmlns:tx&#61;"http://www.springframework.org/schema/tx" xmlns:aop&#61;"http://www.springframework.org/schema/aop"xsi:schemaLocation&#61;"http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/txhttps://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"><context:property-placeholder location&#61;"classpath:db.properties"/><bean id&#61;"dataSource" class&#61;"com.alibaba.druid.pool.DruidDataSource"init-method&#61;"init" destroy-method&#61;"close"><property name&#61;"driverClassName" value&#61;"${jdbc.driverClassName}"/><property name&#61;"url" value&#61;"${jdbc.url}"/><property name&#61;"username" value&#61;"${jdbc.username}"/><property name&#61;"password" value&#61;"${jdbc.password}"/><property name&#61;"initialSize" value&#61;"${jdbc.initialSize}"/>bean><bean id &#61; "accountDao" class&#61;"com.sunny.dao.impl.AccountDaoImpl"><property name&#61;"dataSource" ref&#61;"dataSource"/>bean><bean id&#61;"accountService" class&#61;"com.sunny.service.impl.AccountServiceImpl"><property name&#61;"dao" ref&#61;"accountDao"/>bean><bean id&#61;"txManager" class&#61;"org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name&#61;"dataSource" ref&#61;"dataSource"/>bean><tx:advice id&#61;"txAdvice" transaction-manager&#61;"txManager"><tx:attributes><tx:method name&#61;"trans"/>tx:attributes>tx:advice><aop:config><aop:pointcut id&#61;"txPointcut" expression&#61;"execution(* com.sunny.service.*Service.*(..))"/><aop:advisor advice-ref&#61;"txAdvice" pointcut-ref&#61;"txPointcut"/>aop:config>
beans>
测试
成功!
跳转到目录
通知标签(增强)
子标签
事务方法标签
标签
子标签
跳转到目录
<tx:advice id&#61;"crudAdvice" transaction-manager&#61;"txManager"><tx:attributes><tx:method name&#61;"get*" read-only&#61;"true" propagation&#61;"REQUIRED"/><tx:method name&#61;"list*" read-only&#61;"true" propagation&#61;"REQUIRED"/><tx:method name&#61;"query*" read-only&#61;"true" propagation&#61;"REQUIRED"/><tx:method name&#61;"*" propagation&#61;"REQUIRED"/>tx:attributes>tx:advice>
二、基于 注解 配置声明式事务
跳转到目录
基于注解配置事务
&#xff1a;在Service中&#xff0c;使用 &#64;Transactional注解
&#64;Transactional 注解的属性
public方法将都具有该类型的事务属性
&#xff0c;同时&#xff0c;我们也可以在方法级别使用该标注来覆盖类级别的定义(比如在查询方法上单独设置&#64;Transactional(readOnly&#61;true)。接口方法
、类以及类方法上&#xff0c;但是 Spring 建议不要在接口或者接口方法上使用该注解&#xff0c;因为这只有在使用基于接口的代理时它才会生效。另外&#xff0c; &#64;Transactional 注解应该只被应用到 public 方法上&#xff0c;这是由 Spring AOP 的本质决定的。如果你在 protected、private 或者默认可见性的方法上使用 &#64;Transactional 注解&#xff0c;这将被忽略&#xff0c;也不会抛出任何异常。Java代码
&#64;Repository
public class AccountDaoImpl implements AccountDao {private JdbcTemplate jdbcTemplate;&#64;Autowiredpublic void setDataSource(DataSource ds){this.jdbcTemplate &#61; new JdbcTemplate(ds);}public void transOut(Long outId, int money) {String sql &#61; "UPDATE account SET balance &#61; balance - ? WHERE id &#61; ?";jdbcTemplate.update(sql, money, outId);}public void transIn(Long inId, int money) {String sql &#61; "UPDATE account SET balance &#61; balance &#43; ? WHERE id &#61; ?";jdbcTemplate.update(sql, money, inId);}
}&#64;Service
&#64;Transactional
public class AccountServiceImpl implements AccountService {&#64;Autowiredprivate AccountDao dao;public void trans(Long outId, Long inId, int money) {dao.transOut(outId, money);int a &#61; 1 / 0; // 抛出异常dao.transIn(inId, money);}&#64;Transactional(readOnly &#61; true)public void queryAll(){//TODO}
}
xml配置: 必须要配置 TX注解解析器!
<context:annotation-config/><context:component-scan base-package&#61;"com.sunny"/><bean id&#61;"txManager" class&#61;"org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name&#61;"dataSource" ref&#61;"dataSource"/>bean><tx:annotation-driven transaction-manager&#61;"txManager"/><context:property-placeholder location&#61;"classpath:db.properties"/><bean id&#61;"dataSource" class&#61;"com.alibaba.druid.pool.DruidDataSource"init-method&#61;"init" destroy-method&#61;"close"><property name&#61;"driverClassName" value&#61;"${jdbc.driverClassName}"/><property name&#61;"url" value&#61;"${jdbc.url}"/><property name&#61;"username" value&#61;"${jdbc.username}"/><property name&#61;"password" value&#61;"${jdbc.password}"/><property name&#61;"initialSize" value&#61;"${jdbc.initialSize}"/>bean>
对比
跳转到目录
直接删除xml的配置文件,取而代之的是一个Config类
&#64;Transactional注解&#xff0c;取代tx标签
&#64;EnableTransactionManagement注解&#xff0c;开启事务注解
&#64;Configuration
标识当前类为一个配置类, 当前项目的配置类,好比是applicationContext.xml
&#64;Import(Xxx.class)
在主配置类中包含Xxx的配置类
&#64;PropertySource("classpath:db.properties")
读取配置文件
&#64;Bean("Xxx")
相当于
, Bean()中不写参数,默认就是该方法创建的对象; 该对象就被Spring容器所管理了
该类是一个配置类&#xff0c;它的作用和bean.xml是一样的spring中的新注解Configuration作用&#xff1a;指定当前类是一个配置类细节&#xff1a;当配置类作为AnnotationConfigApplicationContext对象创建的参数时&#xff0c;该注解可以不写。ComponentScan作用&#xff1a;用于通过注解指定spring在创建容器时要扫描的包属性&#xff1a;value&#xff1a;它和basePackages的作用是一样的&#xff0c;都是用于指定创建容器时要扫描的包。我们使用此注解就等同于在xml中配置了:
Java代码
//&#64;Repository("accountDaoImpl")
&#64;Repository // 默认是 accountDaoImpl,相当于类名首字母小写,相当于
public class AccountDaoImpl implements AccountDao {private JdbcTemplate jdbcTemplate;&#64;Autowiredpublic void setDataSource(DataSource ds){this.jdbcTemplate &#61; new JdbcTemplate(ds);}public void transOut(Long outId, int money) {String sql &#61; "UPDATE account SET balance &#61; balance - ? WHERE id &#61; ?";jdbcTemplate.update(sql, money, outId);}public void transIn(Long inId, int money) {String sql &#61; "UPDATE account SET balance &#61; balance &#43; ? WHERE id &#61; ?";jdbcTemplate.update(sql, money, inId);}
}&#64;Service
&#64;Transactional
public class AccountServiceImpl implements AccountService {&#64;Autowiredprivate AccountDao dao;public void trans(Long outId, Long inId, int money) {dao.transOut(outId, money);//int a &#61; 1 / 0; // 抛出异常dao.transIn(inId, money);}
}
Java配置类
//当前项目的配置类,好比是applicationContext.xml
&#64;Configuration //标识当前类为一个配置类
&#64;Import(DataSourceConfig.class) //包含其他的配置类
&#64;ComponentScan("com.sunny") //IoC注解解析器
&#64;EnableTransactionManagement//事务注解解析器
public class JavaConfig {//创建事务管理的Bean&#64;Beanpublic DataSourceTransactionManager txManager(DataSource ds) {return new DataSourceTransactionManager(ds);}
}// 当前项目的连接池的配置类
&#64;Configuration
&#64;PropertySource("classpath:db.properties")
public class DataSourceConfig {// 将properties的内容注入到这些变量中&#64;Value("${jdbc.driverClassName}")private String driverClassName;&#64;Value("${jdbc.url}")private String url;&#64;Value("${jdbc.username}")private String username;&#64;Value("${jdbc.password}")private String password;&#64;Value("${jdbc.initialSize}")private int initialSize;//创建连接池的Bean&#64;Bean("dataSource")public DataSource dataSource() {DruidDataSource ds &#61; new DruidDataSource();ds.setDriverClassName(driverClassName);ds.setUrl(url);ds.setUsername(username);ds.setPassword(password);ds.setInitialSize(initialSize);return ds;}
}
测试类
&#64;RunWith(SpringJUnit4ClassRunner.class)
&#64;ContextConfiguration(classes&#61;JavaConfig.class)
public class SpringTxTest {&#64;Autowiredprivate AccountService service;&#64;Testpublic void test1(){service.trans(10086L, 10010L, 1000);}
}
成功!
使用纯注解和半注解和XML的对比图:
跳转到目录