上篇文章说到了我们创建对象的权利交给了 Spirng ,Spring 会将对象创建好并放入IOC 容器中。我们需要时,直接从 IOC 容器中获取即可。那么 Spring 是什么时候创建对象的呢
一、Bean的生命周期全景图

Bean 的定义与注册
尽管 Spring 接管了对象的创建,但是Spring 也是有原则的,他不会随随便便就创建 Bean。只有你在 Spring 中进行了注册,它才会接管这个对象的创建。
Spring 将自己管理的对象叫做Bean
向 Spring 注册Bean的方式一般有三种:
- XML 配置
- 注解(
@Component、@Service、@Repository) - 配置类
Spring 容器在启动时,会收集需要接管的Bean,把对 Bean 创建的要求打包在一个对象上,它把这个对象叫做BeanDefinition, 完成扫描并创建 BeanDefinition 的 工作的对象叫做BeanDefinitionReader ,收集完后,把所有的 BeanDefinition 放在了一个Map中,叫beanDefinitionMap。
Spring 通过扫描 @Component、@Service、@Repository 等注解,或解析 XML/Java 配置,将类注册为 Bean。
- 核心接口:
BeanDefinition(存储 Bean 的元数据,如作用域、是否懒加载等) 注册方式:
// 注解方式 @Component public class UserService { ... } // 配置类方式 @Configuration public class AppConfig { @Bean public DataSource dataSource() { ... } }xml配置
<bean id="myBean" class="com.example.MyBean"/>
此时Bean 尚未实例化,就像造冰箱时根据客户的要求画好了设计图,但是冰箱还没开始造。
状态:
- 未被实例化,仅以
BeanDefinition形式存在于容器中。 - 元数据已确定(如作用域、懒加载、初始化方法等)。
功能:
- 定义Bean的创建规则,相当于“蓝图”。
- 支持通过
BeanFactoryPostProcessor动态调整元数据。
三.Spring Bean的生命周期
Spring Bean的生命周期是从 Bean 实例化之后,即通过反射创建出对象之后,到Bean成为一个完整对象,最终被销毁。这个过程被称为Spring Bean的生命周期
1. Bean 的实例化
Spring 在创建Bean 前会遍历上面提到的beanDefinitionMap, 拿到BeanDefinition,通过反射来创建 Bean 的实例
- 实例化时机:
- 单例 Bean:容器启动时(默认)或首次调用
getBean()(若配置懒加载) - 原型 Bean:每次
getBean()调用时
- 单例 Bean:容器启动时(默认)或首次调用
此时的状态就像是按照设计图造好了冰箱的外壳,在仓库里已经占用了一块地方。可是里面的各项元件都是空的,根本无法使用。
状态:
- 对象已通过反射创建(调用构造方法),但依赖未注入。
- 此时Bean是“空壳”,字段为
null或默认值。
功能:
- 分配内存空间,完成对象基础构造。
- 单例Bean在此阶段被缓存(若未配置懒加载)。
2. 属性赋值
此时 Spring 为 Bean 设置相关属性和依赖,相关内容我们在上一篇的时候就跟大家讲过了
三种注入方式:
构造器注入(推荐):
@Service public class UserService { private final UserRepository userRepo; // 显式声明依赖 public UserService(UserRepository userRepo) { this.userRepo = userRepo; } }Setter注入:
public class OrderService { private PaymentService paymentService; @Autowired public void setPaymentService(PaymentService paymentService) { this.paymentService = paymentService; } }字段注入(不推荐):
@Service public class ProductService { @Autowired private InventoryService inventoryService; }
技术要点:
- 构造器注入强制依赖完整性,适合必需依赖。
- Setter注入适合可选依赖,支持动态更新。
- 字段注入破坏封装性,难以测试,应谨慎使用。
此时的状态就是内部的元件也都装好了。作为一个冰箱已经可以正常的开始工作了
状态:
- 对象属性被填充(通过构造器、Setter或字段注入)。
- Bean的依赖可能尚未完全初始化(循环依赖场景)。
功能:
- 解决对象间的依赖关系,确保Bean可用。
- 若存在循环依赖,Spring通过三级缓存处理。
3. Bean 的初始化
初始化阶段执行自定义逻辑,顺序如下:
- Aware 接口回调
- BeanPostProcessor 前置处理
@PostConstruct注解方法InitializingBean.afterPropertiesSet()- 自定义
init-method(XML 或@Bean配置)
@Component
public class OrderService {
@PostConstruct
public void init() {
... } // 1. 最先执行
@Override
public void afterPropertiesSet() {
... } // 2. 其次执行
}
AOP代理:
如果Bean被切面(AOP)拦截,它会被动态代理包装:
- JDK动态代理(基于接口)
- CGLIB代理(基于继承)
例子
@Transactional
public void saveUser() {
// 实际执行的是代理对象的增强逻辑
}
状态:
- 依赖已注入完成,Bean处于“就绪”状态。
- 可能已被AOP代理(代理对象替换原始对象)。
功能:
- 执行初始化逻辑(如资源加载、数据预热)。
4. Bean 的使用阶段
若 Bean 被 AOP 代理(如 @Transactional),实际调用的是代理对象的方法。
状态:
- Bean完全初始化,可被其他对象调用。
- 若被AOP代理,实际调用的是代理对象。
功能:
- 执行业务逻辑,响应请求。
- 单例Bean全局共享,原型Bean每次请求独立。
5. Bean 的销毁
容器关闭时,单例 Bean 会执行销毁逻辑,顺序如下:
@PreDestroy注解方法DisposableBean.destroy()- 自定义
destroy-method(XML 或@Bean配置)
@Component
public class DatabasePool {
@PreDestroy
public void cleanup() {
... } // 释放资源
}
状态:
- 单例Bean即将被容器回收,原型Bean不触发此阶段。
- 对象仍存在,但即将被GC回收。
四、扩展点:干预生命周期
当你对Spring 建造的对象不满意时,Spring 提供了两种接口来让你手动干预 Bean 的创建,让你可以定制自己的 Bean
1. BeanPostProcessor
- 干预时机:初始化前后。
- 能力:
- 修改Bean实例(如包装为代理对象)。
- 在
@PostConstruct前插入逻辑。
示例:
@Component
public class LoggingBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String name) {
System.out.println("初始化前:" + name);
return bean;
}
}
2. BeanFactoryPostProcessor
- 干预时机:BeanDefinition注册后,实例化前。
- 能力:
- 修改Bean的作用域、懒加载配置等。
- 动态注册/移除BeanDefinition。
示例:
@Component
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) {
BeanDefinition definition = factory.getBeanDefinition("userService");
definition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
}
}
五、总结:Bean 生命周期关键阶段
- 实例化(Instantiation):通过反射创建Bean对象(调用构造器);
- 属性注入(Populate):自动装配依赖的Bean(DI过程);
- 初始化(Initialization):执行自定义初始化逻辑(三种方式);
- 使用(Ready):Bean存入容器缓存,对外提供服务;
- 销毁(Destruction):Bean被容器回收,资源释放。
📌 注意事项
- 原型 Bean 的销毁需手动管理(Spring 不自动调用销毁方法)。
- 避免在初始化阶段阻塞(如远程调用),否则影响应用启动速度。
- 谨慎使用字段注入,推荐构造器注入以保证不可变性和可测试性。