Spring官网:https://spring.io/

参考视频:

源码仓库:muyoukule/accidence-spring (github.com)

Spring整合JdbcTemplate

JdbcTemplate是Spring提供的一个JDBC模板类,是对JDBC的封装,简化JDBC代码。

环境准备

a. 创建数据表

1
2
3
4
5
6
CREATE TABLE `tbl_user` (
`id` int NOT NULL AUTO_INCREMENT,
`real_name` varchar(255) DEFAULT NULL,
`age` int DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

b. 引入相关依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.27</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
<!--新增的依赖:mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.31</version>
</dependency>
<!--新增的依赖:spring jdbc,这个依赖中有JdbcTemplate-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.27</version>
</dependency>
</dependencies>

c. 准备实体类

1
2
3
4
5
6
7
8
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Integer id;
private String realName;
private Integer age;
}

d. 编写Spring.xml配置文件

JdbcTemplate 是 Spring 提供好的类,这类的完整类名是:org.springframework.jdbc.core.JdbcTemplate

我们怎么使用这个类呢?new对象就可以了。怎么new对象?直接将这个类配置到Spring配置文件中,纳入Bean管理即可。

1
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"></bean>

JdbcTemplate 中有一个 DataSource 属性,这个属性是数据源,我们都知道连接数据库需要 Connection 对象,而生成 Connection 对象是数据源负责的。所以我们需要给 JdbcTemplate 设置数据源属性。

所有的数据源都是要实现 javax.sql.DataSource 接口的。这个数据源可以自己写一个,也可以用写好的。比如:阿里巴巴的德鲁伊连接池,c3p0,dbcp等。

e. 手写一个数据源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Setter
@ToString
public class MyDataSource implements DataSource {

// 添加4个属性
private String driver;
private String url;
private String username;
private String password;

// 重点写怎么获取Connection对象就行。其他方法不用管。
@Override
public Connection getConnection() throws SQLException {
try {
Class.forName(driver);
Connection conn = DriverManager.getConnection(url, username, password);
return conn;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

// --snip--

}

f. 数据源传递给JdbcTemplate

写完数据源,我们需要把这个数据源传递给 JdbcTemplate 。因为 JdbcTemplate 中有一个 DataSource 属性:

1
2
3
4
5
6
7
8
9
<bean id="myDataSource" class="com.muyoukule.Datasource.MyDataSource">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/spring_db"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="myDataSource"/>
</bean>

到这里环境就准备好了。

新增

编写测试程序:

1
2
3
4
5
6
7
8
9
10
11
@Test
public void testInsert() {
// 获取JdbcTemplate对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
// 执行插入操作
// 注意:insert delete update的sql语句,都是执行update方法。
String sql = "insert into tbl_user(id,real_name,age) values(?,?,?)";
int count = jdbcTemplate.update(sql, null, "张三", 30);
System.out.println("插入的记录条数:" + count);
}
1
插入的记录条数:1

update 方法有两个参数:

  • 第一个参数:要执行的 SQL 语句。(SQL语句中可能会有占位符 ? )
  • 第二个参数:可变长参数,参数的个数可以是0个,也可以是多个。一般是 SQL 语句中有几个问号,则对应几个参数。

修改

1
2
3
4
5
6
7
8
9
10
@Test
public void testUpdate() {
// 获取JdbcTemplate对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
// 执行更新操作
String sql = "update tbl_user set real_name = ?, age = ? where id = ?";
int count = jdbcTemplate.update(sql, "张三丰", 55, 1);
System.out.println("更新的记录条数:" + count);
}
1
更新的记录条数:1

删除

1
2
3
4
5
6
7
8
9
10
@Test
public void testDelete() {
// 获取JdbcTemplate对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
// 执行delete
String sql = "delete from tbl_user where id = ?";
int count = jdbcTemplate.update(sql, 1);
System.out.println("删除了几条记录:" + count);
}
1
删除了几条记录:1

查询一个对象

1
2
3
4
5
6
7
8
9
10
@Test
public void testSelectOne() {
// 获取JdbcTemplate对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
// 执行select
String sql = "select id, real_name, age from tbl_user where id = ?";
User user = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(User.class), 2);
System.out.println(user);
}

因为刚才已经将数据库数据删除了,所以需要先插入再测试查询

1
User(id=2, realName=张三, age=30)

queryForObject方法三个参数:

  • 第一个参数:sql语句
  • 第二个参数:Bean属性值和数据库记录行的映射对象。在构造方法中指定映射的对象类型。
  • 第三个参数:可变长参数,给sql语句的占位符问号传值。

查询多个对象

1
2
3
4
5
6
7
8
9
10
@Test
public void testSelectAll() {
// 获取JdbcTemplate对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
// 执行select
String sql = "select id, real_name, age from tbl_user";
List<User> users = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(User.class));
System.out.println(users);
}

查询前先使用不同的数据多次执行插入方法

1
[User(id=2, realName=张三, age=30), User(id=3, realName=李四, age=31), User(id=4, realName=王五, age=32)]

查询一个值

1
2
3
4
5
6
7
8
9
10
@Test
public void testSelectOneValue() {
// 获取JdbcTemplate对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
// 执行select
String sql = "select count(1) from tbl_user";
Integer count = jdbcTemplate.queryForObject(sql, int.class); // 这里用Integer.class也可以
System.out.println("总记录条数:" + count);
}
1
总记录条数:3

批量添加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Test
public void testAddBatch() {
// 获取JdbcTemplate对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
// 批量添加
String sql = "insert into tbl_user(id,real_name,age) values(?,?,?)";

Object[] objs1 = {null, "小花", 20};
Object[] objs2 = {null, "小明", 21};
Object[] objs3 = {null, "小刚", 22};
List<Object[]> list = new ArrayList<>();
list.add(objs1);
list.add(objs2);
list.add(objs3);

int[] count = jdbcTemplate.batchUpdate(sql, list);
System.out.println(Arrays.toString(count));
}
1
[1, 1, 1]

批量修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Test
public void testUpdateBatch() {
// 获取JdbcTemplate对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
// 批量修改
String sql = "update tbl_user set real_name = ?, age = ? where id = ?";
Object[] objs1 = {"小花11", 10, 5};
Object[] objs2 = {"小明22", 12, 6};
Object[] objs3 = {"小刚33", 9, 7};
List<Object[]> list = new ArrayList<>();
list.add(objs1);
list.add(objs2);
list.add(objs3);

int[] count = jdbcTemplate.batchUpdate(sql, list);
System.out.println(Arrays.toString(count));
}
1
[1, 1, 1]

批量删除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Test
public void testDeleteBatch() {
// 获取JdbcTemplate对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
// 批量删除
String sql = "delete from tbl_user where id = ?";
Object[] objs1 = {5};
Object[] objs2 = {6};
Object[] objs3 = {7};
List<Object[]> list = new ArrayList<>();
list.add(objs1);
list.add(objs2);
list.add(objs3);
int[] count = jdbcTemplate.batchUpdate(sql, list);
System.out.println(Arrays.toString(count));
}
1
[1, 1, 1]

使用回调函数

使用回调函数,可以参与的更加细节:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Test
public void testCallback() {
// 获取JdbcTemplate对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
String sql = "select id, real_name, age from tbl_user where id = ?";

User user = jdbcTemplate.execute(sql, new PreparedStatementCallback<User>() {
@Override
public User doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException {
User user = null;
ps.setInt(1, 2);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
user = new User();
user.setId(rs.getInt("id"));
user.setRealName(rs.getString("real_name"));
user.setAge(rs.getInt("age"));
}
return user;
}
});
System.out.println(user);
}
1
User(id=2, realName=张三, age=30)

使用德鲁伊连接池

之前数据源是用我们自己写的。也可以使用别人写好的。例如德鲁伊连接池。

a. 引入德鲁伊连接池的依赖。

1
2
3
4
5
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>

b. 将德鲁伊中的数据源配置到 spring 配置文件中。和配置我们自己写的一样。

1
2
3
4
5
6
7
8
9
10
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/spring_db"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="druidDataSource"/>
</bean>
1
User(id=2, realName=张三, age=30)

Spring整合Mybatis

1. Spring整合Mybatis思路分析

环境准备

在准备环境的过程中,先回顾下Mybatis开发的相关内容:

a. 准备数据库表

Mybatis是来操作数据库表,所以先创建一个数据库及表

1
2
3
4
5
6
7
create database spring_db character set utf8;
use spring_db;
create table tbl_account(
id int primary key auto_increment,
name varchar(35),
money double
);

b. 引入相关依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.27</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.31</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
</dependencies>

c. 根据表创建模型类

1
2
3
4
5
6
7
8
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Account implements Serializable {
private Integer id;
private String name;
private Double money;
}

d. 创建 Dao 接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public interface AccountDao {

@Insert("insert into tbl_account(name,money)values(#{name},#{money})")
void save(Account account);

@Delete("delete from tbl_account where id = #{id} ")
void delete(Integer id);

@Update("update tbl_account set name = #{name} , money = #{money} where id = #{id} ")
void update(Account account);

@Select("select * from tbl_account")
List<Account> findAll();

@Select("select * from tbl_account where id = #{id} ")
Account findById(Integer id);
}

e. 创建 Service 接口和实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public interface AccountService {

void save(Account account);

void delete(Integer id);

void update(Account account);

List<Account> findAll();

Account findById(Integer id);

}

@Service
public class AccountServiceImpl implements AccountService {

@Autowired
private AccountDao accountDao;

public void save(Account account) {
accountDao.save(account);
}

public void update(Account account) {
accountDao.update(account);
}

public void delete(Integer id) {
accountDao.delete(id);
}

public Account findById(Integer id) {
return accountDao.findById(id);
}

public List<Account> findAll() {
return accountDao.findAll();
}
}

f. 添加 jdbc.properties 文件

resources 目录下添加,用于配置数据库连接四要素

1
2
3
4
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_db?useSSL=false
jdbc.username=root
jdbc.password=root

useSSL:关闭 MySQL 的 SSL 连接

g. 添加 Mybatis 核心配置文件(SqlMapConfig.xml)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--读取外部properties配置文件-->
<properties resource="jdbc.properties"/>
<!--别名扫描的包路径-->
<typeAliases>
<package name="com.muyoukule.Entity"/>
</typeAliases>
<!--数据源-->
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--映射文件扫描包路径-->
<mappers>
<package name="com.muyoukule.Dao"/>
</mappers>
</configuration>

h. 编写应用程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class App {
public static void main(String[] args) throws IOException {
// 1. 创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 2. 加载SqlMapConfig.xml配置文件
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
// 3. 创建SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
// 4. 获取SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 5. 执行SqlSession对象执行查询,获取结果User
AccountDao accountDao = sqlSession.getMapper(AccountDao.class);

Account ac = accountDao.findById(1);
System.out.println(ac);

// 6. 释放资源
sqlSession.close();
}
}

i. 运行程序

1
null

结果为 null 是因为数据库还未插入数据。

整合思路分析

Mybatis 的基础环境我们已经准备好了,接下来就得分析下在上述的内容中,哪些对象可以交给 Spring 来管理?

  • Mybatis程序核心对象分析

    从图中可以获取到,真正需要交给Spring管理的是 SqlSessionFactory

  • 整合 Mybatis,就是将 Mybatis 用到的内容交给 Spring 管理,分析下配置文件

    说明:

    • 第一行读取外部 properties 配置文件,Spring有提供具体的解决方案 @PropertySource,需要交给Spring
    • 第二行起别名包扫描,为 SqlSessionFactory 服务的,需要交给 Spring
    • 第三行主要用于做连接池,Spring 之前我们已经整合了 Druid 连接池,这块也需要交给 Spring
    • 前面三行一起都是为了创建 SqlSession 对象用的,那么用 Spring 管理 SqlSession 对象吗?回忆下 SqlSession 是由SqlSessionFactory 创建出来的,所以只需要将 SqlSessionFactory 交给 Spring 管理即可。
    • 第四行是 Mapper 接口和映射文件(如果使用注解就没有该映射文件),这个是在获取到 SqlSession 以后执行具体操作的时候用,所以它和 SqlSessionFactory 创建的时机都不在同一个时间,可能需要单独管理。

2. Spring整合Mybatis

前面我们已经分析了 Spring 与 Mybatis 的整合,大体需要做两件事:

  1. Spring 要管理 MyBatis 中的 SqlSessionFactory

  2. Spring 要管理 Mapper 接口的扫描

实现步骤

a. 项目中导入整合需要的 jar 包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!--Spring操作数据库需要该jar包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.27</version>
</dependency>
<!--
Spring与Mybatis整合的jar包
这个jar包mybatis在前面,是Mybatis提供的
-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.5</version>
</dependency>

b. 创建 Spring 的主配置类

1
2
3
4
5
6
//配置类注解
@Configuration
//包扫描,主要扫描的是项目中的AccountServiceImpl类
@ComponentScan("com.muyoukule")
public class SpringConfig {
}

c. 创建数据源的配置类

在配置类中完成数据源的创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class JdbcConfig {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String userName;
@Value("${jdbc.password}")
private String password;

@Bean
public DataSource dataSource() {
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(userName);
ds.setPassword(password);
return ds;
}
}

d. 主配置类中读 properties 并引入数据源配置类

1
2
3
4
5
6
@Configuration
@ComponentScan("com.muyoukule")
@PropertySource("classpath:jdbc.properties")
@Import(JdbcConfig.class)
public class SpringConfig {
}

e. 创建 Mybatis 配置类并配置 SqlSessionFactory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class MybatisConfig {
//定义bean,SqlSessionFactoryBean,用于产生SqlSessionFactory对象
@Bean
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) {
SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
//设置模型类的别名扫描
ssfb.setTypeAliasesPackage("com.muyoukule.Entity");
//设置数据源
ssfb.setDataSource(dataSource);
return ssfb;
}

//定义bean,返回MapperScannerConfigurer对象
@Bean
public MapperScannerConfigurer mapperScannerConfigurer() {
MapperScannerConfigurer msc = new MapperScannerConfigurer();
msc.setBasePackage("com.muyoukule.Dao");
return msc;
}
}

说明:

  • 使用 SqlSessionFactoryBean 封装 SqlSessionFactory 需要的环境信息

    • SqlSessionFactoryBean 是前面我们讲解 FactoryBean 的一个子类,在该类中将 SqlSessionFactory 的创建进行了封装,简化对象的创建,我们只需要将其需要的内容设置即可。
    • 方法中有一个参数为 dataSource,当前Spring容器中已经创建了Druid数据源,类型刚好是 DataSource 类型,此时在初始化 SqlSessionFactoryBean 这个对象的时候,发现需要使用 DataSource 对象,而容器中刚好有这么一个对象,就自动加载了 DruidDataSource 对象。
  • 使用 MapperScannerConfigurer 加载 Dao 接口,创建代理对象保存到 IOC 容器中

    • 这个 MapperScannerConfigurer 对象也是 MyBatis 提供的专用于整合的 jar 包中的类,用来处理原始配置文件中的 mappers 相关配置,加载数据层的 Mapper 接口类
    • MapperScannerConfigurer 有一个核心属性 basePackage,就是用来设置所扫描的包路径

f. 主配置类中引入 Mybatis 配置类

1
2
3
4
5
6
@Configuration
@ComponentScan("com.muyoukule")
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class, MybatisConfig.class})
public class SpringConfig {
}

g. 编写运行类

在运行类中,从 IOC 容器中获取 Service 对象,调用方法获取结果

1
2
3
4
5
6
7
8
9
10
11
12
public class App2 {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
AccountService accountService = ctx.getBean(AccountService.class);

Account tom = new Account(1, "Tom", 1000.00);
accountService.save(tom);

Account ac = accountService.findById(1);
System.out.println(ac);
}
}

h. 运行程序

1
Account(id=1, name=Tom, money=1000.0)

Spring整合Junit

整合 Junit 与整合 Druid 和 MyBatis 差异比较大,为什么呢?Junit是一个搞单元测试用的工具,它不是我们程序的主体,也不会参加最终程序的运行,从作用上来说就和之前的东西不一样,它不是做功能的,看做是一个辅助工具就可以了。

环境准备

这块环境,大家可以直接使用 Spring 与 Mybatis 整合的环境即可。当然也可以重新创建一个。

整合Junit

a. 引入依赖

pom.xml

1
2
3
4
5
6
7
8
9
10
11
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.27</version>
</dependency>

b. 编写测试类

在 test\java下创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//设置类运行器
@RunWith(SpringJUnit4ClassRunner.class)
//设置Spring环境对应的配置类
@ContextConfiguration(classes = {SpringConfig.class}) //加载配置类
//@ContextConfiguration(locations={"classpath:applicationContext.xml"})//加载配置文件
public class AccountServiceTest {
//支持自动装配注入bean
@Autowired
private AccountService accountService;

@Test
public void testFindById() {
System.out.println(accountService.findById(1));
}

@Test
public void testFindAll() {
System.out.println(accountService.findAll());
}
}
1
2
[Account(id=1, name=Tom, money=1000.0)]
Account(id=1, name=Tom, money=1000.0)

注意:

  • 单元测试,如果测试的是注解配置类,则使用@ContextConfiguration(classes = 配置类.class)
  • 单元测试,如果测试的是配置文件,则使用@ContextConfiguration(locations={配置文件名,...})
  • Junit运行后是基于 Spring 环境运行的,所以 Spring 提供了一个专用的类运行器,这个务必要设置,这个类运行器就在 Spring 的测试专用包中提供的,导入的坐标就是这个东西SpringJUnit4ClassRunner
  • 上面两个配置都是固定格式,当需要测试哪个 bean 时,使用自动装配加载对应的对象,下面的工作就和以前做 Junit 单元测试完全一样了。