Spring 框架从入门到精通(第一篇)—— 框架核心与 IOC 容器实践
作为 Java EE 领域的 “事实标准” 框架,Spring 凭借其 “解耦、灵活、可扩展” 的特性,成为企业级开发的基石。无论是微服务架构还是传统单体应用,Spring 都能提供强大的支撑。本系列博客将分三篇,从基础到实战带你吃透 Spring—— 第一篇聚焦 “框架核心概念” 与 “IOC 容器”,帮你理解 Spring 的设计思想,掌握对象创建与管理的核心能力。
目录
一、为什么要学 Spring?从 Java EE 痛点说起
1.1 传统 Java EE 开发的 3 大痛点
1.2 Spring 的 “救世主” 解决方案
1.3 Spring 的核心架构:不止是 “一层框架”
二、Spring 核心概念:IOC 与 DI 是什么?
2.1 IOC:控制反转,让对象 “自己找主人”
生活案例:从 “自己做饭” 到 “外卖点餐”
代码对比:传统方式 vs Spring IOC 方式
2.2 DI:依赖注入,IOC 的 “具体实现”
DI 的 3 种常见实现方式
三、Spring 环境搭建:从 0 到 1 创建第一个 Spring 项目
3.1 步骤 1:创建 Maven 项目,配置依赖
3.2 步骤 2:创建 Spring 核心配置文件
3.3 步骤 3:创建实体类(POJO)
3.4 步骤 4:编写测试类,从 IOC 容器获取对象
3.5 普通 Java 项目搭建(备选)
四、IOC 容器创建对象的 5 种方式
4.1 方式 1:无参构造创建(默认,最常用)
4.2 方式 2:有参构造创建(适合必填依赖)
配置示例 1:通过参数名匹配
配置示例 2:通过参数索引匹配
配置示例 3:通过参数类型匹配(避免歧义)
4.3 方式 3:实例工厂创建(复用现有工厂类)
步骤 1:创建实例工厂类
步骤 2:配置 Spring 文件
4.4 方式 4:静态工厂创建(无需工厂对象)
步骤 1:创建静态工厂类
步骤 2:配置 Spring 文件
4.5 方式 5:注解创建(企业开发主流)
步骤 1:开启注解扫描
步骤 2:用注解声明 Bean
衍生注解(语义化区分)
五、Bean 的作用域与生命周期:控制对象的 “存活规则”
5.1 Bean 的 6 种作用域
配置作用域:XML 方式 vs 注解方式
测试原型模式:
5.2 Bean 的生命周期:从 “出生” 到 “死亡”
自定义生命周期方法:XML 方式
自定义生命周期方法:注解方式
测试生命周期:
六、总结与下一步预告
一、为什么要学 Spring?从 Java EE 痛点说起
在学习 Spring 之前,我们先搞懂一个关键问题:为什么 Spring 能成为 Java 开发的 “必修课”? 答案藏在传统 Java EE 开发的痛点里。
1.1 传统 Java EE 开发的 3 大痛点
企业级应用(如电商系统、OA 系统)往往具备 “结构复杂、事务密集、高并发” 的特点,传统 Java EE 开发面临三大难题:
- 耦合度高:层与层之间依赖紧密(如 Service 层直接
new DaoImpl()
),修改一个类可能导致多个类联动修改,维护成本极高; - 扩展性差:新增功能时需改动大量现有代码(如添加日志记录、权限检查),不符合 “开闭原则”;
- 重复代码多:数据库连接管理、事务控制等通用逻辑需在每个方法中重复编写,开发效率低。
举个例子:传统 MVC 开发中,Service 层调用 Dao 层的代码是这样的:
// 传统方式:Service直接依赖Dao实现类,耦合度高
public class UserServiceImpl implements UserService {// 硬编码依赖,DaoImpl修改时需改动此处private UserDao userDao = new UserDaoImpl();@Overridepublic User findUserById(int id) {// 重复的数据库连接、事务控制代码Connection conn = null;try {conn = DBUtil.getConnection();conn.setAutoCommit(false);User user = userDao.find(id);conn.commit();return user;} catch (Exception e) {try { conn.rollback(); } catch (SQLException ex) {}throw new RuntimeException(e);} finally {DBUtil.close(conn); // 重复的资源关闭代码}}
}
这种写法的问题很明显:Service 与 DaoImpl 强耦合,通用逻辑(连接、事务)重复,扩展性差。
1.2 Spring 的 “救世主” 解决方案
Spring 框架由 Rod Johnson 于 2003 年推出,核心目标是 “解决 Java EE 开发的复杂性”。它的解决方案可以总结为 **“两大核心 + 一个原则”**:
- 两大核心:IOC(控制反转)解耦对象依赖,AOP(面向切面编程)提取通用逻辑;
- 一个原则:不重复造轮子(如整合 MyBatis、Hibernate 等现有框架,而非替代它们)。
Spring 的优势体现在三个维度:
- 解耦:通过 IOC 容器管理对象创建与依赖,避免硬编码
new
对象; - 提效:AOP 提取日志、事务等通用逻辑,减少重复代码;
- 整合:无缝对接 MyBatis、Spring MVC、Redis 等框架,形成 “一站式” 开发解决方案。
用 Spring 改造后,上述 Service 层代码会变成这样(后续章节详解):
// Spring方式:依赖由容器注入,无硬编码,无重复逻辑
@Service
public class UserServiceImpl implements UserService {// 只依赖接口,不依赖实现类,耦合度低@Autowiredprivate UserDao userDao;@Override@Transactional // 注解声明事务,无需手动控制public User findUserById(int id) {// 只关注业务逻辑,通用逻辑由Spring自动处理return userDao.find(id);}
}
对比可见:Spring 帮我们解决了 “依赖管理” 和 “通用逻辑” 两大问题,开发者只需专注业务实现。
1.3 Spring 的核心架构:不止是 “一层框架”
很多初学者以为 Spring 只是 “一个框架”,其实它是一个分层架构的生态体系,覆盖从持久层到表现层的全链路解决方案。Spring Framework 的核心模块如下图所示,每个模块可独立使用,也可组合协作:
模块分类 | 核心模块 | 功能说明 |
---|---|---|
核心容器 | Core、Beans、Context | 提供 IOC 容器支持,负责对象创建、依赖注入;Context 模块扩展容器功能(如国际化、事件) |
切面编程 | AOP、Aspects | 实现 AOP 功能,支持日志、事务等横切逻辑的提取与织入 |
数据访问 | JDBC、ORM、Transactions | 封装 JDBC 操作,整合 MyBatis/Hibernate,提供声明式事务管理 |
Web 支持 | Web、Web MVC | 支持 Web 开发,提供 Spring MVC 框架,实现 MVC 分层 |
测试支持 | Test | 整合 JUnit,支持 Spring 容器下的单元测试 |
关键认知:Spring 不是 “替换” 现有框架,而是 “整合” 它们。例如:它不重复实现 ORM 功能,而是通过spring-orm
模块让 MyBatis、Hibernate 更易用;它不替代 JDBC,而是通过spring-jdbc
模块简化连接管理。
二、Spring 核心概念:IOC 与 DI 是什么?
IOC(控制反转)是 Spring 的 “灵魂”,理解它就等于掌握了 Spring 的一半。很多初学者对 IOC 的概念感到抽象,我们用 “生活案例 + 代码对比” 帮你彻底搞懂。
2.1 IOC:控制反转,让对象 “自己找主人”
先拆解 “控制反转” 这四个字:
- 控制:指 “对象创建的控制权”(即
new
对象的操作); - 反转:指对象创建的控制权从 “程序员手动控制” 反转到 “Spring 容器自动控制”。
生活案例:从 “自己做饭” 到 “外卖点餐”
传统开发像 “自己做饭”:想吃什么菜(创建对象),必须自己买食材(new
依赖对象)、开火做饭(初始化)、洗碗(资源释放),全程手动操作;
Spring 开发像 “外卖点餐”:你只需告诉平台想吃什么(配置对象需求),平台会自动帮你准备餐食(创建对象)、配送到家(注入依赖),你只需专注 “吃”(业务逻辑)。
代码对比:传统方式 vs Spring IOC 方式
对比维度 | 传统方式(手动控制) | Spring IOC 方式(容器控制) |
---|---|---|
对象创建 | 程序员new 对象(如UserDao userDao = new UserDaoImpl() ) | Spring 容器自动创建(配置后通过getBean() 获取) |
依赖管理 | 硬编码依赖,修改需改代码 | 容器自动注入依赖,无硬编码 |
资源释放 | 手动关闭连接、释放资源 | 容器自动管理对象生命周期(创建→使用→销毁) |
IOC 的核心价值:将对象的 “创建、依赖、销毁” 等通用逻辑交给容器处理,开发者专注业务逻辑,实现 “高内聚、低耦合”。
2.2 DI:依赖注入,IOC 的 “具体实现”
很多人会混淆 IOC 和 DI,其实两者是 “同一概念的不同角度”:
- IOC:从 “对象控制权” 的角度描述 —— 对象创建权反转到容器;
- DI(Dependency Injection):从 “依赖传递” 的角度描述 —— 容器在创建对象时,自动将其依赖的对象注入(赋值)给它。
简单说:IOC 是思想,DI 是实现手段。例如:Spring 容器创建UserServiceImpl
时,会自动将UserDao
对象注入到userDao
属性中,无需程序员手动set
。
DI 的 3 种常见实现方式
Spring 支持三种依赖注入方式,后续章节会详细实战:
- 构造注入:通过构造方法传递依赖(适合必填依赖);
- 设值注入:通过
set
方法传递依赖(适合可选依赖,最常用); - 注解注入:通过
@Autowired
、@Resource
等注解自动注入(企业开发主流)。
三、Spring 环境搭建:从 0 到 1 创建第一个 Spring 项目
理解了核心概念后,我们动手搭建 Spring 环境。和 MyBatis 类似,Spring 环境搭建分为 “普通 Java 项目” 和 “Maven 项目” 两种方式,这里重点讲解企业开发常用的Maven 项目搭建。
3.1 步骤 1:创建 Maven 项目,配置依赖
新建 Maven 项目(ArtifactId 设为spring-demo
),在pom.xml
中添加 Spring 核心依赖:
<dependencies><!-- 1. Spring核心依赖:Core + Beans + Context + Expression --><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>4.1.6.RELEASE</version> <!-- 稳定版本,适配多数企业项目 --></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>4.1.6.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>4.1.6.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-expression</artifactId><version>4.1.6.RELEASE</version></dependency><!-- 2. 日志依赖:Spring默认依赖commons-logging --><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version></dependency><!-- 3. 单元测试依赖 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope></dependency>
</dependencies>
依赖说明:
spring-core
:提供 Spring 框架的基础服务(如资源加载);spring-beans
:提供 BeanFactory(IOC 容器核心);spring-context
:提供 ApplicationContext(扩展的 IOC 容器,支持注解、事件等);commons-logging
:Spring 的日志依赖,无需额外配置即可打印容器日志。
3.2 步骤 2:创建 Spring 核心配置文件
在src/main/resources
目录下新建 Spring 核心配置文件applicationContext.xml
(命名约定,可自定义),这是 IOC 容器的 “配置入口”:
<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 配置Bean:告诉Spring需要管理的对象 --><!-- 语法:<bean id="唯一标识" class="类的全限定名"/> --><bean id="user" class="com.jr.pojo.User"/></beans>
关键标签说明:
<beans>
:根标签,所有 Bean 配置都在其中;<bean>
:声明一个需要 Spring 管理的对象,id
是唯一标识(后续通过id
获取对象),class
是类的全限定名(Spring 通过反射创建对象)。
3.3 步骤 3:创建实体类(POJO)
在src/main/java/com/jr/pojo
目录下创建User
类,作为 Spring 管理的对象:
package com.jr.pojo;public class User {private String name;private int age;// 无参构造方法(Spring默认通过无参构造创建对象,必须提供)public User() {}// 有参构造(可选,后续用于构造注入)public User(String name, int age) {this.name = name;this.age = age;}// getter/setter(用于设值注入)public String getName() { return name; }public void setName(String name) { this.name = name; }public int getAge() { return age; }public void setAge(int age) { this.age = age; }// 业务方法(测试用)public void eat() {System.out.println(name + "(" + age + "岁)在吃汉堡~");}@Overridepublic String toString() {return "User{" + "name='" + name + '\'' + ", age=" + age + '}';}
}
注意:Spring 默认通过 “无参构造” 创建对象,因此实体类必须包含无参构造(若手动写了有参构造,需显式定义无参构造)。
3.4 步骤 4:编写测试类,从 IOC 容器获取对象
在src/test/java/com/jr/test
目录下创建SpringTest
类,通过 Spring 容器获取User
对象并调用方法:
package com.jr.test;import com.jr.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class SpringTest {@Testpublic void testIOC() {// 1. 加载Spring核心配置文件,初始化IOC容器// ApplicationContext:Spring容器接口,ClassPathXmlApplicationContext从类路径加载配置文件ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");// 2. 从容器中获取对象:两种方式// 方式1:通过bean的id获取,返回Object类型,需强制转换User user1 = (User) context.getBean("user");// 方式2:通过id+类型获取,无需强制转换(推荐)User user2 = context.getBean("user", User.class);// 3. 调用对象方法(验证对象由容器创建)user1.setName("张三");user1.setAge(20);user1.eat(); // 输出:张三(20岁)在吃汉堡~// 验证:容器默认创建单例对象(user1和user2是同一个对象)System.out.println(user1 == user2); // 输出:true}
}
运行结果分析:
- 控制台输出
张三(20岁)在吃汉堡~
,说明User
对象由 Spring 容器成功创建; user1 == user2
为true
,说明 Spring 默认创建单例对象(容器中同一个id
的 Bean 只存在一个实例)。
3.5 普通 Java 项目搭建(备选)
若不使用 Maven,需手动导入 Spring 核心 Jar 包,步骤如下:
- 下载 Spring 核心 Jar 包(官网地址:https://repo.spring.io/libs-release-local/org/springframework/spring/);
- 导入以下 Jar 包到项目
lib
目录:- spring-core-4.1.6.RELEASE.jar
- spring-beans-4.1.6.RELEASE.jar
- spring-context-4.1.6.RELEASE.jar
- spring-expression-4.1.6.RELEASE.jar
- commons-logging-1.2.jar(日志依赖);
- 后续步骤(创建配置文件、实体类、测试类)与 Maven 项目一致。
四、IOC 容器创建对象的 5 种方式
Spring 提供多种创建对象的方式,覆盖不同场景(如默认无参构造、有参构造、工厂模式)。掌握这些方式,能应对复杂项目的对象管理需求。
4.1 方式 1:无参构造创建(默认,最常用)
这是 Spring 创建对象的默认方式,只需在applicationContext.xml
中配置<bean>
标签,Spring 会自动调用类的无参构造创建对象。
配置示例:
<!-- 无参构造创建User对象:id=user,class=User全限定名 -->
<bean id="user" class="com.jr.pojo.User"/>
适用场景:大多数简单对象(如 POJO、Dao、Service),无特殊初始化需求。
4.2 方式 2:有参构造创建(适合必填依赖)
若对象需要通过有参构造初始化(如创建User
时必须指定name
和age
),可通过<constructor-arg>
标签传递参数。
配置示例 1:通过参数名匹配
<!-- 有参构造创建User:name匹配构造方法参数名 -->
<bean id="userWithParam" class="com.jr.pojo.User"><!-- <constructor-arg name="参数名" value="参数值"/> --><constructor-arg name="name" value="李四"/><constructor-arg name="age" value="25"/>
</bean>
配置示例 2:通过参数索引匹配
若构造方法参数名可能变化,可通过index
(从 0 开始)指定参数位置:
<!-- 有参构造创建User:index匹配参数位置(0=第一个参数,1=第二个参数) -->
<bean id="userWithIndex" class="com.jr.pojo.User"><constructor-arg index="0" value="王五"/> <!-- 第一个参数:name --><constructor-arg index="1" value="30"/> <!-- 第二个参数:age -->
</bean>
配置示例 3:通过参数类型匹配(避免歧义)
若构造方法有多个重载(如User(String name, int age)
和User(int age, String name)
),可通过type
指定参数类型:
<!-- 有参构造创建User:type指定参数类型,避免歧义 -->
<bean id="userWithType" class="com.jr.pojo.User"><constructor-arg type="java.lang.String" value="赵六"/> <!-- 类型:String --><constructor-arg type="int" value="35"/> <!-- 类型:int -->
</bean>
测试验证:
@Test
public void testConstructorParam() {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");User user = context.getBean("userWithParam", User.class);System.out.println(user); // 输出:User{name='李四', age=25}
}
4.3 方式 3:实例工厂创建(复用现有工厂类)
若项目中已有 “实例工厂类”(需先创建工厂对象才能生成目标对象),Spring 可通过factory-bean
和factory-method
调用工厂方法创建对象。
步骤 1:创建实例工厂类
package com.jr.factory;import com.jr.pojo.User;// 实例工厂:需先创建工厂对象,再调用方法生成User
public class UserInstanceFactory {// 工厂方法:生成User对象public User createUser() {// 可在此处添加复杂初始化逻辑(如读取配置、参数校验)return new User("工厂创建的用户", 28);}
}
步骤 2:配置 Spring 文件
<!-- 1. 先创建实例工厂对象 -->
<bean id="userFactory" class="com.jr.factory.UserInstanceFactory"/><!-- 2. 通过工厂对象的方法创建User:factory-bean=工厂id,factory-method=工厂方法名 -->
<bean id="userByInstanceFactory" class="com.jr.pojo.User"factory-bean="userFactory" factory-method="createUser"/>
4.4 方式 4:静态工厂创建(无需工厂对象)
若工厂类的方法是static
(无需创建工厂对象即可调用),Spring 可直接通过class
和factory-method
调用静态方法创建对象。
步骤 1:创建静态工厂类
package com.jr.factory;import com.jr.pojo.User;// 静态工厂:无需创建工厂对象,直接调用静态方法
public class UserStaticFactory {// 静态工厂方法public static User createUser() {return new User("静态工厂创建的用户", 32);}
}
步骤 2:配置 Spring 文件
<!-- 静态工厂创建User:class=工厂类,factory-method=静态方法名 -->
<bean id="userByStaticFactory" class="com.jr.factory.UserStaticFactory"factory-method="createUser"/>
4.5 方式 5:注解创建(企业开发主流)
上述 XML 配置方式虽清晰,但当 Bean 数量多时(如 hundreds 个),XML 文件会变得臃肿。Spring 提供注解方式,可通过@Component
、@Service
等注解快速声明 Bean,无需 XML 配置。
步骤 1:开启注解扫描
在applicationContext.xml
中添加注解扫描配置,告诉 Spring 哪些包下的类需要扫描注解:
<?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" <!-- 引入context命名空间 -->xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.3.xsd"><!-- 开启注解扫描:扫描com.jr包及其子包下的所有类 --><context:component-scan base-package="com.jr"/></beans>
步骤 2:用注解声明 Bean
在类上添加@Component
(或其衍生注解),Spring 会自动扫描并创建对象:
package com.jr.pojo;import org.springframework.stereotype.Component;// @Component:声明此类由Spring管理,默认Bean id为"user"(类名首字母小写)
// 可自定义id:@Component("myUser")
@Component
public class User {// 类内容与之前一致...
}
衍生注解(语义化区分)
@Component
有三个衍生注解,功能完全相同,仅用于 “语义化区分”(让代码更易读):
@Service
:用于 Service 层类(如UserServiceImpl
);@Repository
:用于 Dao 层类(如UserDaoImpl
);@Controller
:用于 Controller 层类(如UserController
)。
示例:Service 层用@Service
注解:
package com.jr.service.impl;import com.jr.service.UserService;
import org.springframework.stereotype.Service;@Service // 语义化注解,等同于@Component
public class UserServiceImpl implements UserService {// 业务逻辑...
}
测试验证:
@Test
public void testAnnotation() {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");// 通过默认id(类名首字母小写)获取注解声明的BeanUser user = context.getBean("user", User.class);user.setName("注解创建的用户");user.eat(); // 输出:注解创建的用户(0岁)在吃汉堡~
}
五、Bean 的作用域与生命周期:控制对象的 “存活规则”
创建对象后,我们还需要控制对象的 “存活规则”—— 比如 “整个应用只有一个实例” 还是 “每次获取都新建实例”,这就需要了解 Bean 的作用域和生命周期。
5.1 Bean 的 6 种作用域
Spring 提供 6 种作用域,其中单例(singleton) 和原型(prototype) 是核心,其余 4 种仅用于 Web 环境:
作用域 | 说明 | 适用场景 |
---|---|---|
singleton | 默认值,容器中只存在一个实例,所有请求共享(单例模式) | 无状态对象(如 Service、Dao) |
prototype | 每次getBean() 都创建新实例(原型模式) | 有状态对象(如 POJO、Request) |
request | Web 环境中,每个 HTTP 请求创建一个实例,请求结束后销毁 | Web 请求相关对象 |
session | Web 环境中,每个 HTTP Session 创建一个实例,Session 过期后销毁 | 会话相关对象(如用户信息) |
application | Web 环境中,整个 Web 应用共享一个实例,应用停止后销毁 | 全局配置对象 |
globalSession | Portlet 环境中,全局 Session 共享一个实例(极少用) | Portlet 应用 |
配置作用域:XML 方式 vs 注解方式
- XML 方式:通过
<bean>
的scope
属性配置:<!-- 原型模式:每次获取都新建实例 --> <bean id="userPrototype" class="com.jr.pojo.User" scope="prototype"/>
- 注解方式:通过
@Scope
注解配置:import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component;@Component @Scope("prototype") // 配置为原型模式 public class User {// ... }
测试原型模式:
@Test
public void testScope() {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");// 原型模式:两次getBean()获取不同实例User user1 = context.getBean("userPrototype", User.class);User user2 = context.getBean("userPrototype", User.class);System.out.println(user1 == user2); // 输出:false(不同实例)
}
5.2 Bean 的生命周期:从 “出生” 到 “死亡”
Spring Bean 的生命周期可分为 7 个阶段,理解生命周期有助于我们在 “特定时机” 执行自定义逻辑(如初始化资源、释放资源):
- 实例化:Spring 通过反射创建 Bean 实例(调用无参构造);
- 属性注入:容器为 Bean 的属性注入依赖(调用
set
方法或构造方法); - 初始化前:调用
BeanPostProcessor
的postProcessBeforeInitialization
(增强 Bean,如 AOP 代理); - 初始化:执行自定义初始化逻辑(如
init-method
指定的方法、@PostConstruct
注解的方法); - 初始化后:调用
BeanPostProcessor
的postProcessAfterInitialization
(最终增强); - 使用:Bean 处于就绪状态,供应用程序调用;
- 销毁:容器关闭时,执行自定义销毁逻辑(如
destroy-method
指定的方法、@PreDestroy
注解的方法)。
自定义生命周期方法:XML 方式
通过<bean>
的init-method
和destroy-method
指定初始化、销毁方法:
public class User {// 初始化方法:Bean创建后执行public void init() {System.out.println("User初始化:初始化资源(如加载配置)");}// 销毁方法:容器关闭时执行public void destroy() {System.out.println("User销毁:释放资源(如关闭连接)");}// 其他方法...
}
<!-- 配置初始化和销毁方法 -->
<bean id="userLifecycle" class="com.jr.pojo.User"init-method="init" destroy-method="destroy"/>
自定义生命周期方法:注解方式
通过@PostConstruct
(初始化)和@PreDestroy
(销毁)注解,无需 XML 配置:
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.stereotype.Component;@Component
public class User {// 初始化方法:Bean创建后执行@PostConstructpublic void init() {System.out.println("User初始化:注解方式");}// 销毁方法:容器关闭时执行@PreDestroypublic void destroy() {System.out.println("User销毁:注解方式");}// 其他方法...
}
测试生命周期:
@Test
public void testLifecycle() {// 注意:需用ClassPathXmlApplicationContext,它有close()方法ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");User user = context.getBean("userLifecycle", User.class);System.out.println("使用User对象...");// 关闭容器,触发销毁方法context.close();
}
运行结果:
User初始化:初始化资源(如加载配置)
使用User对象...
User销毁:释放资源(如关闭连接)
六、总结与下一步预告
第一篇博客我们聚焦 Spring 的 “基石”——IOC 容器,核心知识点总结如下:
- Spring 的价值:解决传统 Java EE 的 “高耦合、低扩展、重复代码多” 痛点,通过 IOC 和 AOP 简化开发;
- IOC 与 DI:IOC 是 “对象控制权反转” 的思想,DI 是 “依赖注入” 的实现手段,两者共同实现解耦;
- 环境搭建:Maven 项目通过配置依赖快速搭建,普通项目需手动导入 Jar 包;
- Bean 创建方式:无参构造(默认)、有参构造、工厂模式、注解方式(企业主流);
- Bean 生命周期:掌握作用域(单例 / 原型)和自定义初始化、销毁方法。
第二篇预告:我们将深入 Spring 的 “另一核心”——依赖注入(DI) 与AOP(面向切面编程),重点讲解:
- DI 的 3 种实现方式(设值注入、构造注入、注解注入);
- AOP 的核心概念(切面、通知、切点)与手动实现;
- Spring AOP 的 XML 与注解配置(日志、权限案例)。
跟着系列博客一步步实战,你会发现 Spring 的核心逻辑并不复杂 —— 关键是理解 “容器管理对象” 和 “切面提取通用逻辑” 的设计思想,后续的高级特性(如事务、整合 MyBatis)都是基于这两大核心展开的。