IOC/DI配置管理第三方bean
数据库连接配置详解
数据库连接四要素
properties
# 数据库连接配置
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/spring_db?useSSL=false&serverTimezone=UTC
jdbc.username=root
jdbc.password=root
jdbc是自定义的,后面会提到
驱动类 ( .driver)
什么是驱动类?
- 驱动类是Java程序与数据库通信的桥梁
- 不同数据库有不同的驱动类
如何确定驱动类?
- 先确定数据库类型和版本
因为不同数据库、不同版本的对应的驱动类不同。
方法一:
bash
# 连接到数据库后执行
mysql> SELECT version();
方法二:查看项目依赖
因为不同版本的驱动jar包不同,所以需要查看项目使用了哪个数据库驱动jar包以及这个jar包的版本号,以找到对应的驱动类名
查看项目的pom.xml文件,确定使用的数据库驱动版本(如果是新项目,则需要自己添加项目依赖):
xml
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version> <!-- 这个就是版本号 -->
</dependency>
<!-- 这个版本支持 com.mysql.cj.jdbc.Driver 驱动类 -->
方法三:如果使用Navicat、DBeaver等工具,通常在连接信息中就能看到数据库和版本号。
- 再参考具体对应关系:
properties
# MySQL 8.0及以上版本
jdbc.driver=com.mysql.cj.jdbc.Driver
# MySQL 5.x版本
jdbc.driver=com.mysql.jdbc.Driver
# Oracle数据库
jdbc.driver=oracle.jdbc.OracleDriver
# PostgreSQL数据库
jdbc.driver=org.postgresql.Driver
# SQL Server数据库
jdbc.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
连接URL ( .url)
参考官方文档能找到URL的正确格式和必要参数: MySQL Connector/J 开发者指南 / Connector/J 参考 / 连接 URL 语法
URL格式解析:
ini
jdbc:mysql://主机地址:端口号/数据库名?参数1=值1&参数2=值2
各部分含义:
properties
# 本地MySQL,数据库名为spring_db
jdbc.url=jdbc:mysql://127.0.0.1:3306/spring_db
# 远程服务器,指定字符编码和时区
jdbc.url=jdbc:mysql://192.168.1.100:3306/myapp?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
必要参数:
- MySQL 8.0+ 需要
serverTimezone参数 - 开发环境通常设置
useSSL=false - 可能需要的其他参数:
characterEncoding,allowPublicKeyRetrieval等
用户名和密码
properties
# 根据你的数据库设置填写
jdbc.username=你的数据库用户名
jdbc.password=你的数据库密码
连接池配置参数
连接池数据源类
java
// Druid连接池
com.alibaba.druid.pool.DruidDataSource
// C3P0连接池
com.mchange.v2.c3p0.ComboPooledDataSource
// HikariCP连接池(Spring Boot默认)
com.zaxxer.hikari.HikariDataSource
// Apache DBCP
org.apache.commons.dbcp2.BasicDataSource
properties
# 连接池通用配置
pool.initialSize=5
pool.minIdle=5
pool.maxActive=20
pool.maxWait=60000
参数含义解释
| 参数名 | 含义 | 推荐值 |
|---|---|---|
initialSize |
连接池启动时创建的初始连接数 | 5-10 |
minIdle |
连接池中保持的最小空闲连接数 | 5-10 |
maxActive |
连接池中最大活动连接数 | 20-50 |
maxWait |
获取连接的最大等待时间(毫秒) | 60000 |
关于前缀的解释
自定义前缀只是为了分类管理,可以任意命名,或者不加前缀
properties
# 自定义前缀只是为了分类管理,可以任意命名
database.driver=com.mysql.cj.jdbc.Driver
database.url=jdbc:mysql://...
database.username=root
connection.initialSize=5
connection.maxActive=20
# 或者不加前缀
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://...
username=root
案例:数据源对象管理
在本节中,我们将通过实际案例学习如何配置和管理第三方jar包中的bean。我们将使用两种常见的数据源Druid(德鲁伊)和 C3P0为例进行演示。
环境准备
-
创建Maven项目

-
pom.xml依赖配置
xml<dependencies> <!-- Spring核心依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.10.RELEASE</version> </dependency> </dependencies> -
Spring配置文件
在resources目录下创建applicationContext.xml:
xml<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 后续将在这里配置数据源bean --> </beans> -
应用程序入口类
javapublic class App { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); } }
思路分析
现在我们来分析如何配置和管理第三方数据源对象:
需求分析: 使用Spring的IOC容器管理Druid和C3P0连接池对象
实现思路:
- 添加第三方依赖 - 在pom.xml中添加Druid(或 C3P0)和数据库驱动的依赖
- 配置第三方Bean - 在Spring配置文件中将第三方类声明为bean
- 属性注入 - 将数据库连接四要素(驱动、URL、用户名、密码)注入到bean中
- 测试验证 - 从IOC容器获取bean并验证配置是否正确
关键技术点:
- 第三方类的识别 :Druid的
com.alibaba.druid.pool.DruidDataSource和C3P0的com.mchange.v2.c3p0.ComboPooledDataSource - 属性注入方式:使用setter方法注入基本类型属性
- 特殊属性处理:对于需要特殊配置的属性(如连接池参数)也需要进行注入
Druid数据源管理实现
步骤1:添加Druid依赖
xml
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
步骤2:配置 第三方bean-DruidDataSource Bean
xml
<beans>
<!-- 管理DruidDataSource对象 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <!-- class="连接池数据源类" -->
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/spring_db"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
</beans>
配置说明:
| 属性名 | 说明 | 示例值 |
|---|---|---|
| driverClassName | 数据库驱动类 | com.mysql.jdbc.Driver |
| url | 数据库连接地址 | jdbc:mysql://localhost:3306/spring_db |
| username | 数据库用户名 | root |
| password | 数据库密码 | root |
注意:请根据实际数据库配置调整连接四要素。
步骤3:从IOC容器获取Bean
java
public class App {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
DataSource dataSource = (DataSource) ctx.getBean("dataSource");
System.out.println(dataSource);
}
}
步骤4:运行验证
程序成功运行并输出DruidDataSource对象,表明第三方bean已被Spring IOC容器成功管理。\ 
Druid程序运行虽然没有报错,但是当调用DruidDataSource的getConnection()方法获取连接的时候,也会因为没有添加MySQL驱动依赖而报错。
C3P0数据源管理实现
步骤1:添加C3P0依赖
xml
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
依赖查找方法:
- 直接通过搜索引擎查询
- 访问 Maven中央仓库

步骤2:配置C3P0 Bean
xml
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring_db"/>
<property name="user" value="root"/>
<property name="password" value="root"/>
<property name="maxPoolSize" value="1000"/>
</bean>
步骤3:解决驱动缺失问题
运行程序时可能出现ClassNotFoundException,提示缺少com.mysql.jdbc.Driver类。
解决方案: 添加MySQL驱动依赖
xml
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
步骤4:验证结果
添加驱动依赖后,程序成功运行并输出C3P0数据源对象。 
关键注意事项
1. 属性配置差异
不同数据源的属性名称可能存在差异,配置时需注意:
| 数据源 | 驱动属性 | URL属性 | 用户名属性 | 密码属性 |
|---|---|---|---|---|
| Druid | driverClassName | url | username | password |
| C3P0 | driverClass | jdbcUrl | user | password |
2. 驱动加载时机
- Druid:初始化时不立即加载驱动,获取连接时才加载
- C3P0:初始化时立即尝试加载驱动(如果不添加MySQL驱动依赖,初始化时即报错)
3. 扩展属性配置
数据源除了基本的四要素外,还可以配置其他属性:
xml
<!-- Druid额外配置示例 -->
<bean class="com.alibaba.druid.pool.DruidDataSource">
<!-- 基础四要素 -->
<property name="driverClassName" value="..."/>
<property name="url" value="..."/>
<property name="username" value="..."/>
<property name="password" value="..."/>
<!-- 连接池配置 -->
<property name="initialSize" value="5"/>
<property name="maxActive" value="20"/>
<property name="maxWait" value="60000"/>
</bean>
加载Properties文件
在上一节中,我们已经完成了Druid和C3P0数据源的配置,但存在以下问题需要优化:
问题分析:
数据源配置中的数据库连接四要素(驱动、URL、用户名、密码)是硬编码形式,直接写在Spring配置文件中不利于后期维护,需要将这些值提取到外部的properties配置文件中,Spring框架需要能够从配置文件中读取属性值并完成属性注入。
第三方Bean属性优化
实现思路
需求目标: 将数据库连接四要素提取到properties配置文件,由Spring加载配置信息并使用这些信息完成属性注入。
实现步骤:
- 在resources目录下创建jdbc.properties配置文件(文件名可自定义)
- 将数据库连接四要素配置到properties文件中
- 在Spring配置文件中加载properties文件
- 使用加载到的值实现属性注入
其中第3、4步骤是实现的关键,需要重点关注。
实现步骤
步骤1:准备properties配置文件
在src/main/resources目录下创建jdbc.properties配置文件,并添加数据库连接配置:
properties
# 数据库连接配置
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/spring_db?useSSL=false&serverTimezone=UTC
jdbc.username=root
jdbc.password=root
# 连接池通用配置
pool.initialSize=5
pool.minIdle=5
pool.maxActive=20
pool.maxWait=60000
步骤2:开启context命名空间
在applicationContext.xml中开启context命名空间:
xml
<?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:context="http://www.springframework.org/schema/context"
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">
<!-- 后续配置将在这里添加 -->
</beans>
步骤3:加载properties配置文件
在Spring配置文件中使用context命名空间下的标签加载properties配置文件:
xml
<!-- 加载properties配置文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
配置说明:
location属性指定配置文件的路径classpath:前缀表示从类路径下查找文件- 类路径包括:
src/main/resources、src/test/resources、以及jar包中的资源 - 不加前缀时,Spring也会尝试从类路径查找,但明确使用
classpath:更安全
- 类路径包括:
- 可以加载多个配置文件,用逗号分隔:
location="classpath:jdbc.properties,classpath:redis.properties"
步骤4:完成属性注入
使用${key}表达式读取properties配置文件中的内容并完成属性注入:
xml
<?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:context="http://www.springframework.org/schema/context"
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">
<!-- 加载properties配置文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 配置数据源 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<!-- 使用${}表达式读取properties中的值 -->
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!-- 连接池参数也使用配置文件 -->
<property name="initialSize" value="${pool.initialSize}"/>
<property name="minIdle" value="${pool.minIdle}"/>
<property name="maxActive" value="${pool.maxActive}"/>
<property name="maxWait" value="${pool.maxWait}"/>
</bean>
</beans>
高级配置选项
多配置文件加载
xml
<!-- 加载多个properties文件 -->
<context:property-placeholder
location="classpath:jdbc.properties,
classpath:redis.properties,
classpath:system.properties"/>
设置字符编码
xml
<!-- 指定properties文件编码 -->
<context:property-placeholder
location="classpath:jdbc.properties"
encoding="UTF-8"/>
忽略资源未找到
xml
<!-- 忽略未找到的资源文件 -->
<context:property-placeholder
location="classpath:jdbc.properties,
classpath:optional.properties"
ignore-resource-not-found="true"/>
忽略无法解析的占位符
xml
<!-- 忽略无法解析的占位符 -->
<context:property-placeholder
location="classpath:jdbc.properties"
ignore-unresolvable="true"/>
注意事项:
- 确保properties文件在类路径下
- 属性key命名要有意义且唯一
- 生产环境中敏感信息建议使用加密或环境变量
- 可以使用
@Value注解在Java代码中直接注入properties值
读取单个属性
实现思路
为了更好地演示从properties配置文件中读取单个属性的效果,我们使用一个新的案例:
需求说明:
- 从properties配置文件中读取key为
name的值 - 将该值注入到BookDao中
- 在BookDao的save方法中打印该属性值
实现步骤:
- 在项目中添加BookDao和BookDaoImpl类
- 为BookDaoImpl添加一个name属性并提供setter方法
- 在jdbc.properties中添加name属性
- 在applicationContext.xml中添加配置,完成配置文件加载和属性注入(
${key})
实现步骤
步骤1:创建项目中的相关类
BookDao接口:
java
package com.itheima.dao;
public interface BookDao {
void save();
}
BookDaoImpl实现类:
java
package com.itheima.dao.impl;
import com.itheima.dao.BookDao;
public class BookDaoImpl implements BookDao {
private String name;
// 为name属性提供setter方法,用于属性注入
public void setName(String name) {
this.name = name;
}
@Override
public void save() {
System.out.println("book dao save ..." + name);
}
}
步骤2:更新properties配置文件
在jdbc.properties配置文件中添加name属性:
properties
# 数据库连接配置
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/spring_db?useSSL=false&serverTimezone=UTC
jdbc.username=root
jdbc.password=root
# 连接池通用配置
pool.initialSize=5
pool.minIdle=5
pool.maxActive=20
pool.maxWait=60000
# 自定义属性 - 用于单个属性读取演示(也可以不额外添加,注入已有属性,如jdbc.driver)
book.name=Spring开发指南
步骤3:配置Spring配置文件
在applicationContext.xml中完成bean配置、properties文件加载和属性注入:
xml
<?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:context="http://www.springframework.org/schema/context"
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">
<!-- 1. 加载properties配置文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 2. 配置BookDao bean并注入单个属性 -->
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
<property name="name" value="${book.name}"/>
</bean>
<!-- 也可以注入已有属性,如 jdbc.driver -->
<!-- <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"> -->
<!-- <property name="name" value="${jdbc.driver}"/> -->
<!-- </bean> -->
<!-- 3. 数据源配置(原有的) -->
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="initialSize" value="${pool.initialSize}"/>
<property name="minIdle" value="${pool.minIdle}"/>
<property name="maxActive" value="${pool.maxActive}"/>
<property name="maxWait" value="${pool.maxWait}"/>
</bean>
</beans>
步骤4:创建测试运行类
App测试类:
java
package com.itheima;
import com.itheima.dao.BookDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
// 1. 创建Spring IOC容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
// 2. 从容器中获取BookDao bean
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
// 3. 调用方法,验证属性注入是否成功
bookDao.save();
}
}
预期运行结果
当运行App类时,控制台应该输出:
book dao save ...Spring开发指南
注意事项
在使用Spring加载properties配置文件时,有几个重要的注意事项需要特别关注。
问题一:键值对的key为username引发的问题
具体问题 :当在properties文件中配置键值对将key设置为username,并打印属性username时,控制台显示的不是username的值,而是当前操作系统的用户名。
问题原因 :<context:property-placeholder/>标签不仅会加载指定的properties文件,还会加载系统的环境变量,而且系统环境变量的优先级更高。
在Windows系统中,通常会有一个USERNAME环境变量,其值为当前登录用户的用户名。
查看系统环境变量:
java
public static void main(String[] args) throws Exception{
Map<String, String> env = System.getenv();
System.out.println(env);
}
// System.getenv():调用Java系统类的方法,获取所有环境变量
// Map<String, String>:环境变量以"键值对"形式存储
// String(键):环境变量名(如:`USERNAME`, `PATH`)
// String(值):环境变量值(如:`zhangsan`, `C:\Windows\system32`)
解决方案
方案1:设置system-properties-mode属性
xml
<!-- 设置不加载系统属性 -->
<context:property-placeholder
location="jdbc.properties"
system-properties-mode="NEVER"/>
system-properties-mode 的可选值:
ENVER:从不加载系统属性FALLBACK:如果没有在指定属性中找到,则回退到系统属性(默认值)OVERRIDE:系统属性覆盖指定的属性
方案2:避免使用冲突的key名称
properties
# 使用有前缀的key,避免与系统环境变量冲突
db.username=root666
jdbc.username=root666
app.username=root666
问题二:多个配置文件的多种加载方式
场景描述:当项目中有多个properties配置文件需要加载时,Spring提供了多种配置方式。
配置文件内容:
jdbc.properties:
properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/spring_db
jdbc.username=root
jdbc.password=root
jdbc2.properties:
properties
username=root666
app.name=图书管理系统
多种加载方式
方式一:明确列出所有文件
xml
<!-- 用逗号分隔多个配置文件 -->
<context:property-placeholder
location="jdbc.properties,jdbc2.properties"
system-properties-mode="NEVER"/>
适用场景:
- 配置文件数量较少
- 需要精确控制加载哪些文件
方式二:使用通配符
xml
<!-- 加载所有properties文件 -->
<context:property-placeholder
location="*.properties"
system-properties-mode="NEVER"/>
注意事项:
- 不够精确,可能加载到不需要的文件
- 文件加载顺序不确定
方式三:使用classpath前缀
xml
<!-- 从类路径根目录加载 -->
<context:property-placeholder
location="classpath:*.properties"
system-properties-mode="NEVER"/>
特点:
- 标准写法
- 只查找当前项目的类路径
- 不会查找依赖项目中的配置文件
方式四:使用classpath*前缀
xml
<!-- 从所有类路径加载 -->
<context:property-placeholder
location="classpath*:*.properties"
system-properties-mode="NEVER"/>
特点:
- 查找当前项目及所有依赖项目的类路径
- 适用于多模块项目
classpath:与classpath:的区别
前缀 搜索范围 行为特点 classpath:当前项目的类路径 找到第一个匹配的资源就停止 classpath*:所有类路径(当前项目+所有依赖) 搜索所有类路径,返回所有匹配的资源
其他重要规则
- 属性覆盖规则 如果多个文件中有相同的key,后加载的会覆盖先加载的
properties
# file1.properties
app.name=默认名称
# file2.properties
app.name=覆盖后的名称
- 编码问题
xml
<!-- 指定properties文件编码 -->
<context:property-placeholder
location="classpath:*.properties"
file-encoding="UTF-8"
system-properties-mode="NEVER"/>
- 忽略未找到的properties配置文件
xml
<!-- 忽略不存在的配置文件 -->
<context:property-placeholder
location="classpath:required.properties,
classpath:optional.properties"
ignore-resource-not-found="true"
system-properties-mode="NEVER"/>
- 忽略无法解析的占位符
xml
<!-- 忽略无法解析的${}占位符 -->
<context:property-placeholder
location="classpath:*.properties"
ignore-unresolvable="true"
system-properties-mode="NEVER"/>
核心容器详解
Spring核心容器是Spring框架的核心组成部分,主要负责Bean的创建、配置和管理。我们可以将核心容器简单理解为ApplicationContext,它是整个IOC(控制反转)功能的基础实现。
两种容器的创建方式
ClassPathXmlApplicationContext(推荐)
类路径下的XML配置文件方式:
java
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
特点:
- 从项目的classpath中查找配置文件
- 路径相对简洁,便于项目迁移
- 实际开发中最常用的方式
FileSystemXmlApplicationContext
文件系统下的XML配置文件方式:
java
ApplicationContext ctx = new FileSystemXmlApplicationContext("D:\\workspace\\spring\\src\\main\\resources\\applicationContext.xml");
特点:
- 从文件系统的绝对路径中查找配置文件
- 需要写完整的绝对路径
- 项目位置变化时需要修改代码,耦合度高
- 了解即可,不推荐使用
Bean的三种获取方式
通过名称获取(需要类型转换)
java
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
优缺点:
- ✅ 简单直接
- ❌ 需要手动类型转换
- ❌ 类型不安全,可能抛出ClassCastException
通过名称和类型获取
java
BookDao bookDao = ctx.getBean("bookDao", BookDao.class);
优缺点:
- ✅ 类型安全,无需强制转换
- ❌ 需要多传递一个类型参数
通过类型获取
java
BookDao bookDao = ctx.getBean(BookDao.class);
优缺点:
- ✅ 代码简洁,无需bean名称
- ❌ 要求容器中该类型只能有一个对应的bean
- ❌ 多个同类型bean时会抛出异常
容器类层次结构
(1)在IDEA中双击shift,输入BeanFactory 
(2)点击进入BeanFactory类,ctrl+h,就能查看到如下结构的层次关系 
从图中可以看出,容器类也是从无到有根据需要一层层叠加上来的,理解下这种设计思想------接口分层:
- 每层接口都专注于特定的功能
- 上层接口继承下层接口的功能
- 这种设计使得Spring容器具有良好的扩展性和灵活性
BeanFactory的使用与延迟加载
BeanFactory基础用法
使用BeanFactory来创建IOC容器的具体实现方式:
java
public class AppForBeanFactory {
public static void main(String[] args) {
// 1. 创建资源对象
Resource resources = new ClassPathResource("applicationContext.xml");
// 2. 创建BeanFactory容器
BeanFactory bf = new XmlBeanFactory(resources);
// 3. 获取Bean对象
BookDao bookDao = bf.getBean(BookDao.class);
bookDao.save();
}
}
BeanFactory与 ApplicationContext 加载时机对比
| 容器类型 | 加载时机 | 特点 |
|---|---|---|
| BeanFactory | 延迟加载 | 只有在调用getBean()时才创建bean实例 |
| ApplicationContext | 立即加载 | 容器初始化时就创建所有配置的bean实例 |
使用BeanFactory:不调用getBean()时,构造函数不会执行
使用ApplicationContext:容器创建时,构造函数立即执行
ApplicationContext实现延迟加载------lazy-init="true"
xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 使用lazy-init="true"实现延迟加载 -->
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl" lazy-init="true"/>
</beans>
小结
bean相关

依赖注入相关

Spring IOC/DI 注解开发
Spring 的 IOC/DI 配置开发虽然功能强大,但在配置文件的编写上相对复杂。为了真正简化代码开发,Spring 提供了注解开发方式。
我们将从两个主要方面讲解 注解开发:
- 注解开发定义 Bean(基于 2.5 版本注解)
- 纯注解开发(基于 3.0 版本注解)
环境准备
建立项目结构 和 初始代码 同前面 IOC和DI入门案例-代码实现 的基本一致。
运行类App改为:
java
public class App {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
System.out.println(bookDao);
}
}
注解开发定义bean
实现步骤
步骤 1: 删除原 XML 配置
删除 XML 配置文件中的所有<bean> 标签配置
步骤 2: Dao 层添加注解
在 BookDaoImpl 类上添加 @Component 注解:
java
@Component("bookDao")
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
}
重要说明:
- 注解应该添加在具体的实现类上,而不能添加在接口上
@Component("bookDao")中的"bookDao"指定了 Bean 的 ID(而非name属性!)
XML 与注解配置对应关系:

步骤 3: 配置包扫描
为了让Spring框架能够扫描到写在类上的注解,在 XML 配置文件中添加 启用组件扫描功能:
xml
<?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:context="http://www.springframework.org/schema/context"
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">
<!-- 配置组件扫描 -->
<context:component-scan base-package="com.itheima"/>
</beans>
配置说明:
| 配置项 | 说明 |
|---|---|
context:component-scan |
启用组件扫描功能 |
base-package |
指定要扫描的包路径,将扫描指定包及其子包中的所有类上的注解 |
包扫描策略建议:
- 精细路径 (如:
com.itheima.dao.impl)- 扫描范围小,速度快
- 需要配置多个包路径
- 粗粒度路径 (如:
com.itheima)- 扫描范围大,速度稍慢
- 配置简单,推荐使用
实践建议: 一般扫描到项目的组织名称(Maven 的 groupId)即可(如:com.itheima)。
步骤 4: 运行测试
运行应用程序验证配置:
java
public class App {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
System.out.println(bookDao);
}
}
输出:
css
com.itheima.dao.impl. BookDaoImpl@73d4cc9e
步骤 5: Service 层添加注解
在 BookServiceImpl 类上添加 @Component 注解:
java
@Component
public class BookServiceImpl implements BookService {
private BookDao bookDao;
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
}
步骤 6: 验证 Service Bean
测试 Service 层的 Bean 定义:
java
public class App {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
System.out.println(bookDao);
// 按类型获取 Bean
BookService bookService = ctx.getBean(BookService.class);
System.out.println(bookService);
}
}
Bean 名称说明:
-
当
@Component不指定名称时,使用默认名称指定 Bean 的 ID -
默认名称:类名首字母小写 (如:
bookServiceImpl) -
也可以通过默认名称获取 Bean:
javaBookService bookService = (BookService) ctx.getBean("bookServiceImpl"); // 默认名称是bookServiceImpl
组件注解详解
注解层次结构
Spring 提供了 @Component 及其衍生注解:
less
@Component
├── @Controller (表现层)
├── @Service (业务层)
└── @Repository (数据层)
各层注解说明
| 注解 | 适用层次 | 主要用途 |
|---|---|---|
@Controller |
表现层 | 标注控制器类 |
@Service |
业务层 | 标注业务逻辑类 |
@Repository |
数据层 | 标注数据访问类 |
@Component |
通用层 | 标注其他组件类 |
注解详细说明
| 属性 | 说明 |
|---|---|
| 名称 | @Component/@Controller/@Service/@Repository |
| 类型 | 类注解 |
| 位置 | 类定义上方 |
| 作用 | 设置该类为 Spring 管理的 Bean |
| 属性 | value:定义 Bean 的 ID(默认值为类名首字母小写) |
分层注解使用示例
java
// 数据层
@Repository
public class UserDaoImpl implements UserDao {
// ...
}
// 业务层
@Service
public class UserServiceImpl implements UserService {
// ...
}
// 表现层
@Controller
public class UserController {
// ...
}
// 其他组件
@Component
public class CustomComponent {
// ...
}
纯注解开发模式
Spring 3.0版本开始支持纯注解开发模式,使用Java类替代传统的XML配置文件,大大简化了Spring应用的配置过程,提高了开发效率。
实现步骤
步骤 1: 创建配置类
首先创建一个普通的Java类作为配置类:
java
public class SpringConfig {
}
步骤 2: 标识配置类
使用@Configuration注解标识该类为Spring配置类,替代 applicationContext.xml配置文件:
java
@Configuration
public class SpringConfig {
}
步骤 3: 配置包扫描
使用@ComponentScan注解配置组件扫描路径,替代 XML中的<context:component-scan/>:
java
@Configuration
@ComponentScan("com.itheima")
public class SpringConfig {
}
步骤 4: 创建运行类并执行
创建新的运行类,使用注解配置方式初始化Spring容器:
java
public class AppForAnnotation {
public static void main(String[] args) {
// 加载配置类初始化容器
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
System.out.println(bookDao);
BookService bookService = ctx.getBean(BookService.class);
System.out.println(bookService);
}
}
核心注解详解
@Configuration
| 属性 | 说明 |
|---|---|
| 名称 | @Configuration |
| 类型 | 类注解 |
| 位置 | 类定义上方 |
| 作用 | 标识该类为Spring配置类 |
| 属性 | value(默认):定义bean的id |
@ComponentScan
| 属性 | 说明 |
|---|---|
| 名称 | @ComponentScan |
| 类型 | 类注解 |
| 位置 | 类定义上方 |
| 作用 | 设置Spring配置类扫描路径,用于加载使用注解格式定义的bean |
| 属性 | value(默认):扫描路径,此路径可以逐层向下扫描 |
| 多包扫描配置 | 多个数据用数组格式(如:@ComponentScan({"com.itheima.service", "com.itheima.dao"})) |
注解替代对象:
@Configuration:标识配置类,替代XML配置文件@ComponentScan:配置组件扫描路径,替代<context:component-scan/>
两种容器初始化方式
加载XML配置文件初始化容器
java
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
加载配置类初始化容器
java
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
ClassPathXmlApplicationContext:用于加载XML配置文件AnnotationConfigApplicationContext:用于加载配置类
注解开发Bean作用范围与生命周期管理
在使用注解完成Bean的基本管理后,本节将学习如何通过注解配置Bean的作用范围和生命周期,替代之前通过XML配置实现的功能。
环境准备
- 创建Maven项目
- 添加Spring依赖
- 创建Spring配置类
java
@Configuration
@ComponentScan("com.itheima")
public class SpringConfig {
}
- 核心类定义
BookDao接口
java
public interface BookDao {
public void save();
}
BookDaoImpl实现类
java
@Repository
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
}
应用程序入口
java
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
BookDao bookDao1 = ctx.getBean(BookDao.class);
BookDao bookDao2 = ctx.getBean(BookDao.class);
System.out.println(bookDao1);
System.out.println(bookDao2);
}
}
Bean的作用范围 @Scope
默认行为验证
运行App类,控制台输出显示两个相同的地址,表明默认情况下Bean是单例的:
kotlin
com.itheima.dao.BookDaoImpl@5e025e70
com.itheima.dao.BookDaoImpl@5e025e70
配置非单例作用域
使用@Scope注解将BookDaoImpl配置为非单例:
java
@Repository
@Scope("prototype") // 设置Bean作用范围为非单例
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
}
再次运行App类,输出显示两个不同的地址,证明Bean已变为非单例:
kotlin
com.itheima.dao.BookDaoImpl@5e025e70
com.itheima.dao.BookDaoImpl@1d296da
注解详解:@Scope
| 属性 | 说明 |
|---|---|
| 名称 | @Scope |
| 类型 | 类注解 |
| 位置 | 类定义上方 |
| 作用 | 设置该类创建对象的作用范围,控制创建的Bean是否为单例对象 |
| 属性 | value:定义Bean作用范围 默认值singleton(单例) 可选值prototype(非单例) |
Bean的生命周期管理 @PostConstruct、@PreDestroy
方法定义与注解配置
通过生命周期方法定义
在BookDaoImpl中添加初始化和销毁方法:
java
@Repository
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
public void init() {
System.out.println("init ...");
}
public void destroy() {
System.out.println("destroy ...");
}
}
通过生命周期注解配置
使用注解标识初始化和销毁方法:
java
@Repository
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
@PostConstruct // 在构造方法之后执行,替代init-method
public void init() {
System.out.println("init ...");
}
@PreDestroy // 在销毁方法之前执行,替代destroy-method
public void destroy() {
System.out.println("destroy ...");
}
}
验证生命周期方法
修改App类以触发销毁方法:
java
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
BookDao bookDao1 = ctx.getBean(BookDao.class);
BookDao bookDao2 = ctx.getBean(BookDao.class);
System.out.println(bookDao1);
System.out.println(bookDao2);
ctx.close(); // 关闭容器,触发销毁方法
}
}
运行结果验证初始化和销毁方法都被正确执行:
kotlin
init ...
com.itheima.dao.BookDaoImpl@5e025e70
com.itheima.dao.BookDaoImpl@1d296da
destroy ...
注解详解
重要提示 :如果@PostConstruct和@PreDestroy注解无法找到,需要添加以下依赖:
xml
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
原因:从JDK9开始,javax.annotation包被从JDK中移除,而这两个注解恰好位于该包中。
@PostConstruct & @PreDestroy
| 属性 | 说明 | 说明 |
|---|---|---|
| 名称 | @PostConstruct | @PreDestroy |
| 类型 | 方法注解 | 方法注解 |
| 位置 | 方法上一行 | 方法上一行 |
| 作用 | 设置该方法为初始化方法 | 设置该方法为销毁方法 |
执行流程:Bean创建 → 构造函数 → @PostConstruct方法 → Bean就绪 → 容器关闭 → @PreDestroy方法
XML配置与注解配置 成分对应关系 :\ 
注解开发依赖注入
Spring框架为了简化开发,提供了注解方式的依赖注入实现。虽然没有直接提供构造函数注入和setter注入的专用注解,但通过自动装配注解可以更简洁地完成依赖注入。
环境准备
建立项目结构的步骤 同前面 IOC和DI入门案例-代码实现 的基本一致
额外添加一个配置类:
java
@Configuration
@ComponentScan("com.itheima")
public class SpringConfig {
}
环境准备好后,运行后会发现有问题:\ 
问题原因 :在BookServiceImpl类中添加了BookDao的属性,并提供了setter方法,但是目前是没有提供配置注入BookDao的,所以bookDao对象为Null,调用其save方法就会报 控指针异常。
@Autowired 按类型注入
在BookServiceImpl类的bookDao属性上添加@Autowired注解实现自动装配:
java
@Service
public class BookServiceImpl implements BookService {
@Autowired
private BookDao bookDao;
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
}
核心要点:
@Autowired可以写在属性上,也可以写在setter方法上- 推荐使用方式:直接写在属性上并删除setter方法
- 工作原理:基于反射机制创建对象,通过暴力反射为私有属性设值
技术原理说明:
- 普通反射只能获取public修饰的内容
- 暴力反射还可以获取private修饰的内容
- 因此无需提供setter方法即可完成依赖注入
多实现类冲突问题
当接口有多个实现类时,会出现注入冲突:
java
@Repository
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...1");
}
}
@Repository
public class BookDaoImpl2 implements BookDao {
public void save() {
System.out.println("book dao save ...2");
}
}
运行结果:报错 NoUniqueBeanDefinitionException
解决方案:按id名称匹配
通过为Bean指定名称来解决多实现类问题:
java
@Repository("bookDao")
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...1");
}
}
@Repository("bookDao2")
public class BookDaoImpl2 implements BookDao {
public void save() {
System.out.println("book dao save ...2");
}
}
@Autowired匹配规则:
- 首先按照类型进行自动装配
- 如果找到多个同类型Bean,则按照变量名 与Bean名称 进行匹配(变量名 指接受注入的属性字段的名称;Bean名称指id属性)
- 变量名
bookDao会匹配到名称id为bookDao的Bean - 找不到匹配的变量名与Bean名称会报错
@Qualifier 按名称注入
当需要明确指定注入特定名称的Bean时,使用@Qualifier注解:
java
@Service
public class BookServiceImpl implements BookService {
@Autowired
@Qualifier("bookDao1")
private BookDao bookDao;
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
}
重要规则:
@Qualifier必须与@Autowired一起使用@Qualifier注解的参数指定要注入的Bean名称id
@Value 简单数据类型注入
对于基本数据类型 和字符串类型 的注入,使用@Value注解:
java
@Repository("bookDao")
public class BookDaoImpl implements BookDao {
@Value("itheima")
private String name;
public void save() {
System.out.println("book dao save ..." + name);
}
}
注意事项:
- 必须确保数据格式匹配(如字符串不能注入到int类型)
- 硬编码方式将值直接写入注解的参数中
@Value注解通常用于从properties配置文件中读取配置值,实现外部化配置管理。
注解读取Properties配置文件 @PropertySource
@PropertySource + @Value 组合实现配置读取
实现步骤
步骤1:创建Properties配置文件
在resource目录下创建配置文件 jdbc.properties:
properties
name=itheima888
步骤2:加载Properties配置文件
在Spring配置类中使用@PropertySource注解加载配置文件:
java
@Configuration
@ComponentScan("com.itheima")
@PropertySource("jdbc.properties")
public class SpringConfig {
}
步骤3:读取配置值
在Bean中使用@Value注解读取配置文件中的值:
java
@Repository("bookDao")
public class BookDaoImpl implements BookDao {
@Value("${name}")
private String name;
// @Value("${app.timeout:5000}") 默认值
// private int timeout;
public void save() {
System.out.println("book dao save ..." + name);
}
}
步骤4:验证结果
运行应用程序,控制台输出应显示配置值已成功加载:
book dao save ...itheima888
高级配置选项
多配置文件加载:支持同时加载多个properties配置文件
java
@PropertySource({"jdbc.properties", "application.properties", "config.properties"})
类路径指定:明确指定从类路径加载配置文件
java
@PropertySource("classpath:jdbc.properties")
❌ 不支持通配符 :不能使用*.properties模式匹配
java
// 错误用法 - 会导致运行报错
@PropertySource({"*.properties"})
技术要点总结
- 注解组合:
@PropertySource+@Value实现配置读取- 路径规范:建议使用
classpath:前缀指定明确路径- 多文件支持:通过数组形式加载多个配置文件
- 默认值支持:
@Value("${key:defaultValue}")语法提供默认值- 编码要求:配置文件必须使用正确的字符编码
注解详解
@Autowired
| 名称 | @Autowired |
|---|---|
| 类型 | 属性注解、方法注解(了解)、方法形参注解(了解) |
| 位置 | 属性定义上方、setter方法上方、方法形参前面 |
| 作用 | 为引用类型属性设置值 |
| 属性 | required:true/false,定义该属性是否允许为null |
@Qualifier
| 属性 | 说明 |
|---|---|
| 类型 | 属性注解、方法注解(了解) |
| 位置 | 属性定义上方、setter方法上方 |
| 作用 | 为引用类型属性指定注入的beanId |
| 属性 | value:设置注入的bean Id |
@Value
| 属性 | 说明 |
|---|---|
| 类型 | 属性注解、方法注解(了解) |
| 位置 | 属性定义上方、setter方法上方 |
| 作用 | 为基本数据类型或字符串类型属性设置值 |
| 属性 | value:要注入的属性值 |
@PropertySource
| 属性 | 说明 |
|---|---|
| 类型 | 类注解 |
| 位置 | 类定义上方 |
| 作用 | 加载properties文件中的属性值 |
| 属性 | value:设置加载的properties文件名 |
IOC/DI注解开发管理第三方bean
在Spring框架中,当我们管理自己开发的类时,可以直接在类上使用注解(如@Component、@Service等)来定义Bean。但对于第三方库中的类,由于无法修改第三方库中的类源代码 ,不能直接在类上添加注解。此时,我们需要使用@Bean注解来灵活地管理第三方Bean。
环境准备
项目结构
- Maven项目
- 添加Spring依赖
- 创建配置类和相关组件
配置类
java
@Configuration
public class SpringConfig {
}
数据访问层
java
public interface BookDao {
public void save();
}
@Repository
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
}
应用启动类
java
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx =
new AnnotationConfigApplicationContext(SpringConfig.class);
}
}
注解开发管理第三方bean
在上述环境中完成对Druid数据源的管理,具体的实现步骤为:
步骤1:添加Druid依赖
xml
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
步骤2:在配置类中创建Bean方法
在配置类中添加一个方法,该方法返回要创建的Bean对象类型,并在方法上添加@Bean注解
java
@Configuration
public class SpringConfig {
@Bean
public DataSource dataSource(){
// 创建Druid数据源实例
DruidDataSource ds = new DruidDataSource();
// 配置数据源连接参数
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
}
关键说明:
- @Bean注解作用:将方法的返回值制作为Spring容器管理的一个Bean对象
- 方法命名:方法名默认作为Bean的名称
- 返回值类型:方法的返回值类型决定了Bean的类型
- 实现方式 :必须使用具体实现类(
DruidDataSource)而非接口(DataSource)来创建实例,因为接口中没有对应的setter方法
步骤3:从IOC容器获取并使用Bean
java
public class App {
public static void main(String[] args) {
// 创建注解配置应用上下文
AnnotationConfigApplicationContext ctx =
new AnnotationConfigApplicationContext(SpringConfig.class);
// 从容器中获取数据源Bean
DataSource dataSource = ctx.getBean(DataSource.class);
System.out.println(dataSource);
// 关闭上下文
ctx.close();
}
}
至此使用@Bean来管理第三方bean的案例就已经完成。
扩展应用:管理多个第三方Bean
如果需要管理多个第三方Bean,只需在配置类中添加多个使用@Bean注解的方法:
java
@Configuration
public class SpringConfig {
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
@Bean
public AnotherThirdPartyBean anotherBean(){
return new AnotherThirdPartyBean();
}
// 可以继续添加更多的@Bean方法...
}
引入外部配置类
概述
在实际项目中,如果将所有的第三方Bean都配置在单一的Spring配置类中,会导致:
- 配置类过于臃肿,代码可读性差
- 不利于按功能模块进行分类管理,维护困难
问题场景
将所有第三方Bean配置在SpringConfig中时:
java
@Configuration
public class SpringConfig {
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
// 其他第三方Bean配置...
// 导致配置类越来越庞大,难以维护
}
为此,Spring提供了两种主要方式来引入外部配置类:包扫描引入、@Import引入。
使用包扫描引入
步骤1:创建独立的配置类
将数据源配置提取到独立的JdbcConfig类中:
java
@Configuration
public class JdbcConfig {
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
}
步骤2:在Spring的配置类中配置包扫描
java
@Configuration
@ComponentScan("com.itheima.config") // 关键:扫描指定包下的所有配置类
public class SpringConfig {
// 主配置类保持简洁
}
步骤3:确保配置类在扫描路径中
JdbcConfig类必须位于com.itheima.config包或其子包下。
优缺点分析
- 优点:自动扫描,配置简单
- 缺点 :
- 无法快速知晓引入了哪些具体配置类
- 依赖包结构,不够灵活
- 不推荐在生产环境中使用
使用@Import引入(推荐)
步骤1:创建配置类(可省略@Configuration)
java
public class JdbcConfig {
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
}
注意 :使用@Import时,配置类上的@Configuration注解可以省略。
步骤2:在Spring配置类中使用@Import引入
java
@Configuration
@Import(JdbcConfig.class)
public class SpringConfig {
// 主配置类
}
-
引入多个配置类 :可以以数组形式引入多个配置类,而不能在一个Spring配置类中多次使用@Import注解
java@Configuration @Import({ JdbcConfig.class, // 数据源配置 CacheConfig.class // 缓存配置 // 可以继续添加其他配置类... }) public class SpringConfig { // 一次性引入多个配置类 }
总结
方案对比
| 特性 | 包扫描方式 | @Import方式 |
|---|---|---|
| 配置复杂度 | 简单 | 简单 |
| 可读性 | 较差 | 优秀 |
| 灵活性 | 依赖包结构 | 灵活指定 |
| 显式控制 | 弱 | 强 |
| 推荐程度 | 不推荐 | 推荐 |
核心注解详解
@Bean 注解
| 属性 | 说明 |
|---|---|
| 名称 | @Bean |
| 类型 | 方法注解 |
| 位置 | 方法定义上方 |
| 作用 | 设置该方法的返回值作为Spring管理的Bean |
| 属性 | value(默认):定义Bean的id,默认值为方法名 |
使用示例:
java
@Bean("myDataSource") // 自定义Bean名称
public DataSource dataSource(){
return new DruidDataSource();
}
@Import 注解
| 属性 | 说明 |
|---|---|
| 名称 | @Import |
| 类型 | 类注解 |
| 位置 | 类定义上方 |
| 作用 | 导入配置类 |
| 属性 | value:定义导入的配置类类名,导入多个时使用数组格式 |
使用示例:
java
@Import({JdbcConfig.class, CacheConfig.class, SecurityConfig.class})
实践推荐
- 按功能模块划分配置
java
// 数据库配置
public class JdbcConfig {
@Bean
public DataSource dataSource() {
// 数据源配置
}
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
}
// 缓存配置
public class CacheConfig {
@Bean
public RedisTemplate redisTemplate() {
// Redis配置
}
}
// 消息队列配置
public class MqConfig {
@Bean
public RabbitTemplate rabbitTemplate() {
// RabbitMQ配置
}
}
- 主配置类统一管理
java
@Configuration
@Import({
JdbcConfig.class, // 数据库相关配置
CacheConfig.class, // 缓存相关配置
MqConfig.class, // 消息队列配置
ServiceConfig.class // 服务层配置
})
@PropertySource("classpath:application.properties")
public class SpringConfig {
// 主配置类保持简洁,只做配置聚合
}
注解开发实现为第三方bean注入资源
概述
在使用@Bean注解创建第三方Bean对象时,经常需要在创建过程中注入其他资源。这些资源主要分为两大类:
- 简单数据类型:字符串、数值等基本类型
- 引用数据类型:其他Spring管理的Bean对象
简单数据类型注入
需求分析
在配置数据源时,数据库连接参数(驱动类名、URL、用户名、密码)不应该硬编码在代码中,而应该从外部配置文件读取,提高配置的灵活性和可维护性。
原始硬编码方式(不推荐):
java
public class JdbcConfig {
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
// 硬编码数据库配置(存在问题)
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
}
实现步骤
步骤1:定义配置属性字段
在配置类中定义需要注入的属性字段:
java
public class JdbcConfig {
// 定义数据库连接配置属性
private String driver;
private String url;
private String userName;
private String password;
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
// 暂时仍使用硬编码(后续改进)
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
}
步骤2:使用@Value注解注入值
使用@Value注解为属性注入具体的值:
java
public class JdbcConfig {
@Value("com.mysql.jdbc.Driver")
private String driver;
@Value("jdbc:mysql://localhost:3306/spring_db")
private String url;
@Value("root")
private String userName;
@Value("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;
}
}
扩展:使用配置文件注入(生产环境推荐)
步骤1:创建properties配置文件
在resources目录下创建jdbc.properties文件:
properties
# 数据库连接配置
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_db
jdbc.username=root
jdbc.password=123456
# 连接池配置
jdbc.initialSize=5
jdbc.maxActive=20
jdbc.minIdle=5
步骤2:加载配置文件并注入属性
java
// 关键:使用@PropertySource加载配置文件
@PropertySource("classpath:jdbc.properties")
public class JdbcConfig {
// 关键:使用${key}格式从配置文件中读取值
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String userName;
@Value("${jdbc.password}")
private String password;
@Value("${jdbc.initialSize:5}") // 默认值5
private int initialSize;
@Value("${jdbc.maxActive:20}") // 默认值20
private int maxActive;
@Value("${jdbc.minIdle:5}") // 默认值5
private int minIdle;
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
// 使用配置文件中的值
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(userName);
ds.setPassword(password);
// 设置连接池参数
ds.setInitialSize(initialSize);
ds.setMaxActive(maxActive);
ds.setMinIdle(minIdle);
return ds;
}
}
步骤3:主配置类引入
java
@Configuration
@Import(JdbcConfig.class)
public class SpringConfig {
// 主配置类
}
@Value注解详解
| 属性 | 说明 |
|---|---|
| 名称 | @Value |
| 类型 | 字段注解、方法参数注解 |
| 位置 | 字段定义上方、方法参数前 |
| 作用 | 为基本数据类型或字符串类型字段注入值 |
| 常用格式 | @Value("硬编码值") @Value("${配置文件key}") @Value("${配置文件key:默认值}") |
引用数据类型注入
需求分析
在创建第三方Bean时,可能需要依赖其他Spring管理的Bean。例如,配置数据源时需要使用BookDao进行某些操作。
实现步骤
步骤1:确保依赖Bean被Spring管理
首先确保BookDao被Spring扫描并管理:
java
// BookDao接口
public interface BookDao {
void save();
void update();
}
// BookDao实现类
@Repository // 关键:让Spring管理此Bean
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
public void update() {
System.out.println("book dao update ...");
}
}
步骤2:配置组件扫描
在主配置类中配置组件扫描路径:
java
@Configuration
// 关键:扫描DAO包,让Spring管理BookDao等组件
@ComponentScan("com.itheima.dao")
@Import({JdbcConfig.class})
public class SpringConfig {
// 主配置类
}
步骤3:在@Bean方法中注入引用类型
在JdbcConfig的dataSource方法中通过参数注入BookDao:
java
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
* 关键:在方法参数中声明需要注入的Bean,Spring会自动装配
*
* @param bookDao Spring会自动注入BookDao实例
* @return DataSource 数据源实例
*/
@Bean
public DataSource dataSource(BookDao bookDao) { //(参数类型 自定义参数名称)
// 可以在这里使用注入的bookDao
System.out.println("注入的BookDao: " + bookDao);
System.out.println("BookDao类型: " + bookDao.getClass().getName());
// 演示使用bookDao
bookDao.save();
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(userName);
ds.setPassword(password);
return ds;
}
/** 可以注入多个依赖Bean的示例 */
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource, BookDao bookDao) {
// 这里同时注入了dataSource和bookDao
System.out.println("创建JdbcTemplate,使用数据源: " + dataSource);
System.out.println("同时可访问BookDao: " + bookDao);
return new JdbcTemplate(dataSource);
}
}
注解开发总结
前面我们已经完成了XML配置和注解的开发实现,对比回顾两者之间的差异:

Spring整合
在进行企业级开发的时候,除了将自己写的类让Spring管理之外,还有一部分重要的工作就是整合第三方的技术。下面结合IoC和DI,整合2个常用技术,进一步加深对Spring的使用理解。
Spring整合Mybatis思路分析
环境准备
在整合之前,我们先回顾Mybatis开发的相关内容,并准备基础环境。
1. 数据库表准备
Mybatis是来操作数据库表,所以先创建一个数据库及表
sql
-- 创建数据库
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
);
2. 项目依赖配置
在pom.xml中添加相关依赖:
xml
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
</dependencies>
3. 模型类创建
根据数据库表创建对应的实体类:
java
public class Account implements Serializable {
private Integer id;
private String name;
private Double money;
// setter、getter、toString方法省略
}
4. 数据访问层接口
创建AccountDao接口,使用Mybatis注解方式:
java
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);
}
5. 业务层实现
创建Service接口和实现类:
java
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();
}
}
6. 配置文件
添加 jdbc.properties - resources目录下添加,用于配置数据库连接四要素:
properties
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连接
添加 Mybatis核心配置文件(SqlMapConfig.xml):
xml
<?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"></properties>
<!-- 别名扫描的包路径 -->
<typeAliases>
<package name="com.itheima.domain"/>
</typeAliases>
<!-- 数据源配置 -->
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<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.itheima.dao"/>
</mappers>
</configuration>
7. 编写应用程序
java
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. 获取Mapper接口代理对象并执行查询
AccountDao accountDao = sqlSession.getMapper(AccountDao.class);
Account account = accountDao.findById(1);
System.out.println(account);
// 6. 释放资源
sqlSession.close();
}
}
8. 运行程序

通过以上步骤,我们完成了Mybatis基础环境的搭建。在后续的整合过程中,我们将使用Spring来管理这些组件,简化开发流程并提高代码的可维护性。
Spring整合Mybatis思路分析
在完成Mybatis基础环境搭建后,我们需要深入分析哪些对象可以交给Spring的IoC容器来管理,以实现两者的无缝整合。
Mybatis程序核心对象分析
通过对Mybatis运行流程的分析,我们可以识别出以下核心组件:

从图中可以获取到,真正需要交给Spring管理的是 SqlSessionFactory ,管理好SqlSessionFactory就等于管理了整个Mybatis的核心,其他组件都可以通过它来间接管理。
Mybatis配置文件分析
整合Mybatis,就是将Mybatis用到的内容交给Spring管理,详细分析Mybatis配置文件中各个部分与Spring整合的关系:

1. 外部properties配置文件读取
xml
<properties resource="jdbc.properties"></properties>
- Spring提供了专门的
@PropertySource注解来加载properties配置文件 - 可以通过
Environment对象或@Value注解来读取配置属性 - 需要交给Spring管理
2. 类型别名包扫描
xml
<typeAliases>
<package name="com.itheima.domain"/>
</typeAliases>
- 在Spring配置中可以通过SqlSessionFactoryBean的
typeAliasesPackage属性设置 - 主要用于为SqlSessionFactory服务
- 我们不需要直接将SqlSession交给Spring管理,SqlSession是由SqlSessionFactory创建出来的,SqlSessionFactory交给Spring管理,让Spring间接控制SqlSession的生命周期。
- 需要交给Spring管理
3. 数据源与连接池配置
xml
<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>
- Spring已经提供了完善的Druid连接池整合方案
- 可以单独配置DataSource bean,实现更好的连接池管理
- 需要交给Spring管理
4. 映射文件扫描配置
xml
<mappers>
<package name="com.itheima.dao"/>
</mappers>
- 在Spring中可以通过MapperScannerConfigurer或
@MapperScan注解实现 - Mapper接口的实例化时机与SqlSessionFactory不同,需要单独管理
- 需要交给Spring管理
- 如果使用注解就没有该映射文件
整合策略总结
| Mybatis组件 | 是否由Spring管理 | Spring整合方案 |
|---|---|---|
| 外部properties配置 | ✅ 是 | @PropertySource + Environment |
| 类型别名扫描 | ✅ 是 | SqlSessionFactoryBean.typeAliasesPackage |
| 数据源连接池 | ✅ 是 | 独立的DataSource Bean配置 |
| SqlSessionFactory | ✅ 是 | SqlSessionFactoryBean |
| SqlSession | ❌ 否 | 由SqlSessionFactory创建,线程级别对象 |
| Mapper接口代理 | ✅ 是 | MapperScannerConfigurer或@MapperScan |
Spring整合Mybatis
通过前面的分析,我们已经明确了Spring整合Mybatis需要完成的两项核心任务:
- Spring管理MyBatis中的SqlSessionFactory
- Spring管理Mapper接口的扫描
下面是具体的实现步骤:
步骤1:添加整合依赖包
在pom.xml中添加必要的依赖:
xml
<dependencies>
<!-- Spring操作数据库需要的jar包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<!-- Spring与Mybatis整合的jar包(由Mybatis提供) -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
</dependencies>
步骤2:创建Spring主配置类
java
/**
* Spring主配置类
* 负责整个应用的核心配置
*/
@Configuration
@ComponentScan("com.itheima") // 包扫描,主要扫描项目中的业务组件如AccountServiceImpl
public class SpringConfig {
// 主配置类,后续会逐步完善
}
步骤3:创建数据源配置类
java
/**
* 数据源配置类
* 负责数据库连接池的配置和管理
*/
public class JdbcConfig {
// 使用@Value注解注入properties文件中的配置值
@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
* @return DruidDataSource实例
*/
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(userName);
ds.setPassword(password);
return ds;
}
}
步骤4:完善主配置类
java
/**
* 完善后的Spring主配置类
* 整合properties配置和数据源配置
*/
@Configuration
@ComponentScan("com.itheima")
@PropertySource("classpath:jdbc.properties") // 加载jdbc.properties配置文件
@Import(JdbcConfig.class) // 引入数据源配置类
public class SpringConfig {
// 现在配置类已经具备了数据库连接的能力
}
步骤5:创建Mybatis配置类
java
/**
* Mybatis配置类
* 负责SqlSessionFactory和Mapper扫描的配置
*/
public class MybatisConfig {
/**
* 定义SqlSessionFactoryBean
* 用于创建SqlSessionFactory对象
*
* @param dataSource 数据源,Spring会自动注入
* @return SqlSessionFactoryBean实例
*/
@Bean
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){
SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
// 设置模型类的别名扫描包路径
ssfb.setTypeAliasesPackage("com.itheima.domain");
// 设置数据源
ssfb.setDataSource(dataSource);
return ssfb;
}
/**
* 定义MapperScannerConfigurer
* 用于扫描Mapper接口并创建代理对象
*
* @return MapperScannerConfigurer实例
*/
@Bean
public MapperScannerConfigurer mapperScannerConfigurer(){
MapperScannerConfigurer msc = new MapperScannerConfigurer();
// 设置Mapper接口的扫描包路径
msc.setBasePackage("com.itheima.dao");
return msc;
}
}
核心组件说明
SqlSessionFactoryBean 的作用原理:
- SqlSessionFactoryBean是Spring的FactoryBean接口的实现类,封装了SqlSessionFactory的创建过程;
- Spring在需要SqlSessionFactory时,自动调用其getObject()方法,getObject()方法内部使用之前通过setter方法设置的配置(数据源、类型别名包等),构建并返回真正的SqlSessionFactory实例,完成Mybatis初始化
- 它简化了配置,我们只需要设置必要的参数(数据源、类型别名包等)
MapperScannerConfigurer 的作用原理
- MapperScannerConfigurer是BeanDefinitionRegistryPostProcessor接口的实现类
- 在Spring容器初始化阶段,它会自动扫描指定包下的所有接口,为每个Mapper接口创建BeanDefinition,并设置其工厂为MapperFactoryBean,MapperFactoryBean再为每个接口创建JDK动态代理对象
- 这样Service层就能直接通过@Autowired注入Mapper接口
步骤6:整合Mybatis配置到主配置类
java
/**
* 完整的Spring主配置类
* 整合了所有必要的配置
*/
@Configuration
@ComponentScan("com.itheima")
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class, MybatisConfig.class}) // 同时引入数据源和Mybatis配置
public class SpringConfig {
// 现在配置类已经完整,包含了数据源和Mybatis的整合配置
}
步骤7:编写运行测试类
java
/**
* 应用运行类
* 测试Spring与Mybatis的整合效果
*/
public class App2 {
public static void main(String[] args) {
// 创建Spring容器(基于注解配置)
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
// 从容器中获取AccountService实例
AccountService accountService = ctx.getBean(AccountService.class);
// 调用业务方法,测试整合效果
Account account = accountService.findById(1);
System.out.println(account);
}
}
步骤8:运行验证
运行程序后,如果控制台正确输出查询结果,说明Spring与Mybatis整合成功。

整合总结
通过以上步骤,我们成功完成了Spring与Mybatis的整合,核心要点包括:
- 两个关键类 :
SqlSessionFactoryBean:负责创建SqlSessionFactoryMapperScannerConfigurer:负责扫描和注册Mapper接口
- 配置分离 :
- 数据源配置独立管理
- Mybatis配置独立管理
- 主配置类统一导入
- 依赖注入 :
- SqlSessionFactory自动注入DataSource
- Service层自动注入Mapper接口
这种整合方式大大简化了Mybatis的使用,让我们能够专注于业务逻辑的开发,而无需关心底层的资源管理和对象创建。
Spring整合JUnit(非 现代JUnit5测试类)
一、整合差异
整合Junit与整合Druid、MyBatis有本质区别:
| 整合类型 | 作用 | 在程序中的角色 |
|---|---|---|
| Druid/MyBatis | 程序功能组件 | 参与程序运行,是程序主体部分 |
| Junit | 单元测试工具 | 不参与最终程序运行,是辅助测试工具 |
二、环境准备
- 基础环境:复用Spring+MyBatis整合项目结构
- 项目结构 直接使用Spring与MyBatis整合的环境:\

三、整合步骤详解
步骤1:添加依赖
xml
<!-- JUnit单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- Spring测试支持 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
步骤2:编写测试类
在test\java下创建一个AccountServiceTest.java,这个.java文件名字自定义
java
// 设置使用Spring的测试运行器
@RunWith(SpringJUnit4ClassRunner.class)
// 设置Spring环境对应的配置类
@ContextConfiguration(classes = {SpringConfiguration.class})
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());
}
}
四、核心注解详解
-
@RunWith - 设置测试运行器,写在测试类定义上方
作用:告诉JUnit不要使用默认的运行器,而是使用指定的运行器java// 固定写法:使用Spring的JUnit运行器 @RunWith(SpringJUnit4ClassRunner.class) -
@ContextConfiguration - 加载Spring配置,写在测试类定义上方
根据配置方式选择其中一种:java// 方式1:加载注解配置类(推荐) @ContextConfiguration(classes = {配置类名.class}) // 方式2:加载XML配置文件 @ContextConfiguration(locations = {"配置文件名.xml"}) // 方式3:加载多个配置,用数组格式表示 @ContextConfiguration(classes = {Config1.class, Config2.class}) @ContextConfiguration(locations = {"classpath:config1.xml", "classpath:config2.xml"})
五、工作原理解析:传统测试 vs Spring整合测试
传统JUnit测试流程 :
启动JUnit → 创建测试类实例 → 执行测试方法(手动创建容器 → 手动获取Bean → 执行测试)
传统测试代码示例(对比):
java
public class TraditionalTest {
@Test
public void testFindById() {
// 手动创建容器
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfiguration.class);
// 手动获取Bean
AccountService accountService = ctx.getBean(AccountService.class);
// 执行测试
System.out.println(accountService.findById(1));
}
}
Spring整合JUnit测试流程 :
启动JUnit → 创建Spring容器 → 从容器中获取测试类实例 → 自动注入依赖 → 执行测试方法
Spring整合JUnit测试代码:
java
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {SpringConfiguration.class})
public class IntegratedTest {
@Autowired // 自动注入
private AccountService accountService;
@Test
public void testFindById() {
// 直接使用注入的Bean
System.out.println(accountService.findById(1));
}
}