Spring知识点整合(下)

此处 @Spring知识点整合(上) 和 @Spring知识点整合(中)
建议先看了上再看下嗷,大佬请无视此句话
我的环境 idea 2019.1
jdk 1.8
Spring 5
Lombok插件 这里是使用和安装链接(包括idea和eclipse) @简单粗暴节省JavaBean代码插件 Lombok.jar
上2篇是 @ 1 - 11 和 @ 12 - 15 16.Spring中的JDBCTemplate详解

1、spring中的JdbcTemplate JdbcTemplate的作用: 它就是用于和数据库交互的,实现对表的CRUD操作 如何创建该对象: 代码中写 对象中的常用方法: 代码中写 2、作业: spring基于AOP的事务控制 3、spring中的事务控制 基于XML的 基于注解的

首先写一个案例:不使用注解的操作
创建一个 maven 项目
添加坐标
4.0.0cn.icanci jdbcTemplate 1.0-SNAPSHOTjar org.springframework spring-context 5.2.2.RELEASE org.springframework spring-jdbc 5.2.2.RELEASE org.springframework spring-tx 5.2.2.RELEASE mysql mysql-connector-java 5.1.35 org.projectlombok lombok 1.18.8 provided

Account.java
package cn.icanci.domain; import lombok.Data; /** * @Author: icanci * @ProjectName: jdbcTemplate * @PackageName: cn.icanci.domain * @Date: Created in 2020/1/10 17:13 * @ClassAction: Account的实体类 */ @Data public class Account { private Integer id; private String name; private Float money; }

JdbcTemplateDemo1 .java
package cn.icanci.jdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DriverManagerDataSource; /** * @Author: icanci * @ProjectName: jdbcTemplate * @PackageName: cn.icanci.jdbcTemplate * @Date: Created in 2020/1/10 17:20 * @ClassAction: JDBCTemplate的最基本用法 */ public class JdbcTemplateDemo1 { public static void main(String[] args) { //准备数据源 : Spring的内置数据源 DriverManagerDataSource ds = new DriverManagerDataSource(); ds.setDriverClassName("com.mysql.jdbc.Driver"); ds.setUrl("jdbc:mysql://localhost:3306/icanci"); ds.setUsername("root"); ds.setPassword("ok"); //1.创建JdbcTemplate JdbcTemplate jdbcTemplate = new JdbcTemplate(); //设置数据源 jdbcTemplate.setDataSource(ds); //2.执行操作 jdbcTemplate.execute("insert into account (name,money) values ('hash',1000)"); } }

测试结果:

Spring知识点整合(下)
文章图片
测试结果 现在使用xml配置的方式 首先配置bean.xml

创建一个类: JdbcTemplateDemo2 .java
package cn.icanci.jdbcTemplate; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DriverManagerDataSource; /** * @Author: icanci * @ProjectName: jdbcTemplate * @PackageName: cn.icanci.jdbcTemplate * @Date: Created in 2020/1/10 17:20 * @ClassAction: JDBCTemplate的最基本用法 */ public class JdbcTemplateDemo2 { public static void main(String[] args) { //1.获取容器 ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); //2.获取对象 JdbcTemplate jdbcTemplate = ac.getBean("jdbcTemplate",JdbcTemplate.class); //3.执行操作 jdbcTemplate.execute("insert into account (name,money) values ('hashTable',4000)"); } }

测试结果:

Spring知识点整合(下)
文章图片
测试结果 实现最基本的增删改查 创建Account 的IAccountDao.java接口
package cn.icanci.dao; import cn.icanci.domain.Account; /** * @Author: icanci * @ProjectName: jdbcTemplate * @PackageName: cn.icanci.dao * @Date: Created in 2020/1/10 20:51 * @ClassAction: 账户的持久层接口 */ public interface IAccountDao { /** * 根据id查询账户 * @param id 需要查询的id * @return 返回查询出的的Account对象 */ Account findAccountById(Integer id); /** * 根据姓名查询用户 * @param name 需要查询的用户 * @return 返回查询的的Account对象 */ Account findAccountByName(String name); /** * 更新操作 * @param account 需要更新的对象 */ void updateAccount(Account account); }

IAccountDao.java的实现类 AccountDaoImpl.java
package cn.icanci.dao.impl; import cn.icanci.dao.IAccountDao; import cn.icanci.domain.Account; import lombok.Setter; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import java.util.List; /** * @Author: icanci * @ProjectName: jdbcTemplate * @PackageName: cn.icanci.dao.impl * @Date: Created in 2020/1/10 21:06 * @ClassAction: 账户的持久层实现类 */ public class AccountDaoImpl implements IAccountDao { @Setter private JdbcTemplate jdbcTemplate; @Override public Account findAccountById(Integer id) { //这个是装x的写法 因为有两次查询 效率会低 //return jdbcTemplate.query("select * from account where id = ?", new BeanPropertyRowMapper<>(Account.class), id).size() == 1 ? jdbcTemplate.query("select * from account where id = ?", new BeanPropertyRowMapper<>(Account.class), id).get(0) : null; List listAccount = jdbcTemplate.query("select * from account where id = ?", new BeanPropertyRowMapper<>(Account.class), id); return listAccount.size() == 1 ? listAccount.get(0) : null; }@Override public Account findAccountByName(String name) { //这个是装x的写法 因为有两次查询 效率会低 //return jdbcTemplate.query("select * from account where name = ?", new BeanPropertyRowMapper<>(Account.class), name).size() == 1 ? jdbcTemplate.query("select * from account where name = ?", new BeanPropertyRowMapper<>(Account.class), name).get(0) : null; List listAccount = jdbcTemplate.query("select * from account where name = ?", new BeanPropertyRowMapper<>(Account.class), name); if (listAccount.isEmpty()) { return null; } if (listAccount.size() > 1) { throw new RuntimeException("结果集不唯一"); } return listAccount.get(0); }@Override public void updateAccount(Account account) { jdbcTemplate.update("update account set name = ?,money = ? where id = ?", account.getName(), account.getMoney(), account.getId()); } }

配置文件 bean.xml

测试类:
package cn.icanci.jdbcTemplate; import cn.icanci.dao.IAccountDao; import cn.icanci.domain.Account; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.jdbc.core.JdbcTemplate; /** * @Author: icanci * @ProjectName: jdbcTemplate * @PackageName: cn.icanci.jdbcTemplate * @Date: Created in 2020/1/10 17:20 * @ClassAction: JDBCTemplate的最基本用法 */ public class JdbcTemplateDemo4 { public static void main(String[] args) { //1.获取容器 ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); //2.获取对象 IAccountDao accountDao = ac.getBean("accountDao", IAccountDao.class); //3.执行操作 Account account = accountDao.findAccountById(100); System.out.println(account); } }

测试结果: 因为我数据库没有100
null

上述代码的优化
编写 JdbcDaoSupport.java 用于抽取Dao中的重复代码
package cn.icanci.dao.impl; import lombok.Data; import lombok.Getter; import lombok.Setter; import org.springframework.jdbc.core.JdbcTemplate; import javax.sql.DataSource; /** * @Author: icanci * @ProjectName: jdbcTemplate * @PackageName: cn.icanci.dao.impl * @Date: Created in 2020/1/10 21:28 * @ClassAction: 用于抽取Dao中的重复代码 */ public class JdbcDaoSupport { @Getter @Setter private JdbcTemplate jdbcTemplate; private DataSource dataSource; public void setDataSource(DataSource dataSource){ this.dataSource = dataSource; if(jdbcTemplate == null){ jdbcTemplate = createJdbcTemplate(dataSource); } } private JdbcTemplate createJdbcTemplate(DataSource datasource){ return new JdbcTemplate(dataSource); } }

AccountDaoImpl.java只需要继承 JdbcDaoSupport.java就可以了
package cn.icanci.dao.impl; import cn.icanci.dao.IAccountDao; import cn.icanci.domain.Account; import lombok.Setter; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import java.util.List; /** * @Author: icanci * @ProjectName: jdbcTemplate * @PackageName: cn.icanci.dao.impl * @Date: Created in 2020/1/10 21:06 * @ClassAction: 账户的持久层实现类 */ public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDao {@Override public Account findAccountById(Integer id) { //这个是装x的写法 因为有两次查询 效率会低 //return jdbcTemplate.query("select * from account where id = ?", new BeanPropertyRowMapper<>(Account.class), id).size() == 1 ? jdbcTemplate.query("select * from account where id = ?", new BeanPropertyRowMapper<>(Account.class), id).get(0) : null; List listAccount = getJdbcTemplate().query("select * from account where id = ?", new BeanPropertyRowMapper<>(Account.class), id); return listAccount.size() == 1 ? listAccount.get(0) : null; }@Override public Account findAccountByName(String name) { //这个是装x的写法 因为有两次查询 效率会低 //return jdbcTemplate.query("select * from account where name = ?", new BeanPropertyRowMapper<>(Account.class), name).size() == 1 ? jdbcTemplate.query("select * from account where name = ?", new BeanPropertyRowMapper<>(Account.class), name).get(0) : null; List listAccount = getJdbcTemplate().query("select * from account where name = ?", new BeanPropertyRowMapper<>(Account.class), name); if (listAccount.isEmpty()) { return null; } if (listAccount.size() > 1) { throw new RuntimeException("结果集不唯一"); } return listAccount.get(0); }@Override public void updateAccount(Account account) { getJdbcTemplate().update("update account set name = ?,money = ? where id = ?", account.getName(), account.getMoney(), account.getId()); } }

测试: 测试通过
null

当然 Spring 也提供了这个类.我们来看一下:

Spring知识点整合(下)
文章图片
Spring提供的JdbcDaoSupport.java
区别就是 :如果使用注解开发 可以使用我们自己手写的 如果使用Spring的,就必须使用xml来进行配置
17.Spring中的声明式事务控制 基于注解和基于xml 重点:基于xml配置的声明式事务控制
/** * Spring中基于XML的声明式事务配置步骤 * 1.配置事务管理器 * 2.配置事务的通知 * 此时需要导入事务的约束 tx的命名空间和约束 同时也需要aop的 * 使用 配置 * 属性:id 唯一标识 * transaction-manager 给事务通知一个事务管理器 * 3.配置AOP的通用切入点表达式 * 4.建立事务和切入点的对应关系 * 5.配置事务的属性 * 实在 tx:advice内部 */

配置事务的属性:
/** * 配置事务的属性 * isolation 用于指定事务的隔离级别 默认是 DEFAULT * propagation 用于指定事务的传播行为默认值是 REQUIRED 表示一定有事物 查询方法可以是 SUPPORTS * read-only 指定事务是否只读只有查询方法才能设置为 true默认值是 false * timeout 用于指定事务的过期时间 默认值是 -1 表示永不超市单位是秒 * rollback-for用于指定一个异常 产生此异常 事务回滚没有默认值 任何都回滚 * no-rollback-for用于指定一个异常 产生此异常 事务不回滚没有默认值 任何都回滚 */

代码区
导入依赖
4.0.0cn.icanci springtx 1.0-SNAPSHOTjar org.springframework spring-context 5.2.2.RELEASE org.springframework spring-jdbc 5.2.2.RELEASE org.springframework spring-tx 5.2.2.RELEASE mysql mysql-connector-java 5.1.35 org.aspectj aspectjweaver 1.9.5 org.projectlombok lombok 1.18.8 provided junit junit 4.12 org.springframework spring-test 5.0.2.RELEASE

Account.java
package cn.icanci.domain; import lombok.Data; /** * @Author: icanci * @ProjectName: jdbcTemplate * @PackageName: cn.icanci.domain * @Date: Created in 2020/1/10 17:13 * @ClassAction: Account的实体类 */ @Data public class Account { private Integer id; private String name; private Float money; }

账户的持久层接口 IAccountDao .java
package cn.icanci.dao; import cn.icanci.domain.Account; /** * @Author: icanci * @ProjectName: jdbcTemplate * @PackageName: cn.icanci.dao * @Date: Created in 2020/1/10 20:51 * @ClassAction: 账户的持久层接口 */ public interface IAccountDao { /** * 根据id查询账户 * @param id 需要查询的id * @return 返回查询出的的Account对象 */ Account findAccountById(Integer id); /** * 根据姓名查询用户 * @param name 需要查询的用户 * @return 返回查询的的Account对象 */ Account findAccountByName(String name); /** * 更新操作 * @param account 需要更新的对象 */ void updateAccount(Account account); }

账户的持久层实现类 AccountDaoImpl .java
package cn.icanci.dao.impl; import cn.icanci.dao.IAccountDao; import cn.icanci.domain.Account; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.support.JdbcDaoSupport; import java.util.List; /** * @Author: icanci * @ProjectName: jdbcTemplate * @PackageName: cn.icanci.dao.impl * @Date: Created in 2020/1/10 21:06 * @ClassAction: 账户的持久层实现类 */ public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDao {@Override public Account findAccountById(Integer id) { //这个是装x的写法 因为有两次查询 效率会低 //return jdbcTemplate.query("select * from account where id = ?", new BeanPropertyRowMapper<>(Account.class), id).size() == 1 ? jdbcTemplate.query("select * from account where id = ?", new BeanPropertyRowMapper<>(Account.class), id).get(0) : null; List listAccount = getJdbcTemplate().query("select * from account where id = ?", new BeanPropertyRowMapper<>(Account.class), id); return listAccount.size() == 1 ? listAccount.get(0) : null; }@Override public Account findAccountByName(String name) { //这个是装x的写法 因为有两次查询 效率会低 //return jdbcTemplate.query("select * from account where name = ?", new BeanPropertyRowMapper<>(Account.class), name).size() == 1 ? jdbcTemplate.query("select * from account where name = ?", new BeanPropertyRowMapper<>(Account.class), name).get(0) : null; List listAccount = getJdbcTemplate().query("select * from account where name = ?", new BeanPropertyRowMapper<>(Account.class), name); if (listAccount.isEmpty()) { return null; } if (listAccount.size() > 1) { throw new RuntimeException("结果集不唯一"); } return listAccount.get(0); }@Override public void updateAccount(Account account) { getJdbcTemplate().update("update account set name = ?,money = ? where id = ?", account.getName(), account.getMoney(), account.getId()); } }

账户的业务层接口 IAccountService .java
package cn.icanci.service; import cn.icanci.domain.Account; /** * @Author: icanci * @ProjectName: springtx * @PackageName: cn.icanci.service * @Date: Created in 2020/1/10 22:10 * @ClassAction: 账户的业务层接口 */ public interface IAccountService { /** * 根据id查询账户 * @param id 需要查询的id * @return 返回查询出的的Account对象 */ Account findAccountById(Integer id); /** * 转账 * @param sourceName 转出 * @param targetName 转入 * @param money 转账金额 */ void transfer(String sourceName,String targetName,Float money); }

AccountServiceImpl .java
package cn.icanci.service.impl; import cn.icanci.dao.IAccountDao; import cn.icanci.domain.Account; import cn.icanci.service.IAccountService; import org.springframework.beans.factory.annotation.Autowired; /** * @Author: icanci * @ProjectName: springtx * @PackageName: cn.icanci.service.impl * @Date: Created in 2020/1/10 22:12 * @ClassAction: */public class AccountServiceImpl implements IAccountService { @Autowired private IAccountDao accountDao; @Override public Account findAccountById(Integer id) { return accountDao.findAccountById(id); }@Override public void transfer(String sourceName, String targetName, Float money) { //第一步:根据名称查询转出账户 Account source = accountDao.findAccountByName(sourceName); //第二步:根据名称查询转入账户 Account target = accountDao.findAccountByName(targetName); //第三步:转出账户捡钱 source.setMoney(source.getMoney() - money); //第四步:转入账户价钱 target.setMoney(target.getMoney() + money); //第五步:更新转出账户 accountDao.updateAccount(source); int i = 1 / 0; //第六步:更新转入账户 accountDao.updateAccount(target); } }

bean.xml配置文件
【Spring知识点整合(下)】

测试类:
package cn.icanci.test; import cn.icanci.dao.IAccountDao; import cn.icanci.service.IAccountService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * @Author: icanci * @ProjectName: springtx * @PackageName: cn.icanci.test * @Date: Created in 2020/1/10 22:19 * @ClassAction: */@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:bean.xml") public class AccountServiceTest { @Autowired private IAccountService accountService; @Test public void testTransfer() { accountService.transfer("aaa", "bbb", 111F); } }

测试通过的,可以完成事务的回滚
重点:基于注解配置的声明式事务控制 非纯注解 基于上一个修改的代码如下:
AccountDaoImpl.java
package cn.icanci.dao.impl; importjava.lang.ref.Reference; import cn.icanci.dao.IAccountDao; import cn.icanci.domain.Account; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.support.JdbcDaoSupport; import org.springframework.stereotype.Repository; import java.util.List; /** * @Author: icanci * @ProjectName: jdbcTemplate * @PackageName: cn.icanci.dao.impl * @Date: Created in 2020/1/10 21:06 * @ClassAction: 账户的持久层实现类 */ @Repository("accountDao") public class AccountDaoImpl implements IAccountDao {@Autowired private JdbcTemplate jdbcTemplate; @Override public Account findAccountById(Integer id) { //这个是装x的写法 因为有两次查询 效率会低 //return jdbcTemplate.query("select * from account where id = ?", new BeanPropertyRowMapper<>(Account.class), id).size() == 1 ? jdbcTemplate.query("select * from account where id = ?", new BeanPropertyRowMapper<>(Account.class), id).get(0) : null; List listAccount = jdbcTemplate.query("select * from account where id = ?", new BeanPropertyRowMapper<>(Account.class), id); return listAccount.size() == 1 ? listAccount.get(0) : null; }@Override public Account findAccountByName(String name) { //这个是装x的写法 因为有两次查询 效率会低 //return jdbcTemplate.query("select * from account where name = ?", new BeanPropertyRowMapper<>(Account.class), name).size() == 1 ? jdbcTemplate.query("select * from account where name = ?", new BeanPropertyRowMapper<>(Account.class), name).get(0) : null; List listAccount = jdbcTemplate.query("select * from account where name = ?", new BeanPropertyRowMapper<>(Account.class), name); if (listAccount.isEmpty()) { return null; } if (listAccount.size() > 1) { throw new RuntimeException("结果集不唯一"); } return listAccount.get(0); }@Override public void updateAccount(Account account) { jdbcTemplate.update("update account set name = ?,money = ? where id = ?", account.getName(), account.getMoney(), account.getId()); } }

AccountServiceImpl.java
package cn.icanci.service.impl; import cn.icanci.dao.IAccountDao; import cn.icanci.domain.Account; import cn.icanci.service.IAccountService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; /** * @Author: icanci * @ProjectName: springtx * @PackageName: cn.icanci.service.impl * @Date: Created in 2020/1/10 22:12 * @ClassAction: */ @Service("accountService") @Transactional(propagation = Propagation.SUPPORTS,readOnly = true) public class AccountServiceImpl implements IAccountService { @Autowired private IAccountDao accountDao; @Override public Account findAccountById(Integer id) { return accountDao.findAccountById(id); }@Transactional(propagation = Propagation.REQUIRED,readOnly = false) @Override public void transfer(String sourceName, String targetName, Float money) { //第一步:根据名称查询转出账户 Account source = accountDao.findAccountByName(sourceName); //第二步:根据名称查询转入账户 Account target = accountDao.findAccountByName(targetName); //第三步:转出账户捡钱 source.setMoney(source.getMoney() - money); //第四步:转入账户价钱 target.setMoney(target.getMoney() + money); //第五步:更新转出账户 accountDao.updateAccount(source); //int i = 1 / 0; //第六步:更新转入账户 accountDao.updateAccount(target); } }

bean.xml配置

其他不变:测试通过的
重点:基于注解配置的声明式事务控制 纯注解 现在可以直接删除掉 bean.xml 不过可以一边配置一边删除
依然使用上述的例子 这里只给出修改部分的代码
增加配置类 SpringConfiguration.java
package cn.icanci.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.context.annotation.PropertySource; import org.springframework.transaction.annotation.EnableTransactionManagement; import javax.annotation.Resource; /** * @Author: icanci * @ProjectName: springtx * @PackageName: cn.icanci.config * @Date: Created in 2020/1/10 23:12 * @ClassAction: Spring的配置类 相当于 bean.xml */ @Configuration @ComponentScan("cn.icanci") @Import({JdbcConfiguration.class,TransactionConfiguration.class}) @PropertySource("jdbcConfigurate.properties") @EnableTransactionManagement public class SpringConfiguration { }

增加配置类 配置数据库链接 JdbcConfiguration .java
package cn.icanci.config; importjava.beans.Beans; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.jdbc.datasource.DriverManagerDataSource; import javax.sql.DataSource; import java.sql.DatabaseMetaData; import java.sql.DriverManager; /** * @Author: icanci * @ProjectName: springtx * @PackageName: cn.icanci.config * @Date: Created in 2020/1/10 23:13 * @ClassAction: 和练级数据库相关的配置类 */ public class JdbcConfiguration { @Value("${jdbc.driver}") private String driver; @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String username; @Value("${jdbc.password}") private String password; /** * 创建JdbcTemplate * @param datasource * @return */ @Bean(name="jdbcTemplate") public JdbcTemplate createJdbcTemplate(DataSource datasource){ return new JdbcTemplate(datasource); } @Bean(name = "datasource") public DataSource createDataSource(){ DriverManagerDataSource ds = new DriverManagerDataSource(); ds.setDriverClassName(driver); ds.setUrl(url); ds.setUsername(username); ds.setPassword(password); returnds; } }

增加配置类 处理事务 TransactionConfiguration.java
package cn.icanci.config; import org.springframework.context.annotation.Bean; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import javax.sql.DataSource; /** * @Author: icanci * @ProjectName: springtx * @PackageName: cn.icanci.config * @Date: Created in 2020/1/10 23:26 * @ClassAction:用于创建事务管理器的类 */ public class TransactionConfiguration { /** * 用于创建事务管理器 * @param dataSource * @return */ @Bean(name = "transactionManagement") public PlatformTransactionManager createTransactionManager(DataSource dataSource){ return new DataSourceTransactionManager(dataSource); } }

增加配置文件 jdbcConfigurate.properties
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/icanci jdbc.username=root jdbc.password=ok

修改测试类 AccountServiceTest.java 并且测试
package cn.icanci.test; import cn.icanci.config.SpringConfiguration; import cn.icanci.dao.IAccountDao; import cn.icanci.service.IAccountService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * @Author: icanci * @ProjectName: springtx * @PackageName: cn.icanci.test * @Date: Created in 2020/1/10 22:19 * @ClassAction: */@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = SpringConfiguration.class) public class AccountServiceTest { @Autowired private IAccountService accountService; @Test public void testTransfer() { accountService.transfer("aaa", "bbb", 111F); } }

最后是测试通过的
18.Spring中的编程式事务控制 这里暂时不写了,编程式事务控制开发中很少使用
至此 Spring的知识点整合到此告一段落
之后的学习中有需要的会进行补充
华丽的分割线
此处 @我自己 这是QQ聊天的链接 欢迎一起吹
此处 @Spring知识点整合(上) 和 @Spring知识点整合(中)

    推荐阅读