Spring IOC 与 Bean 生命周期
IOC(控制反转)
什么是 IOC?
IOC(Inversion of Control):控制反转,将对象的创建和管理权交给 Spring 容器。
传统方式:程序主动创建对象
new UserService();
new UserDao();
IOC 方式:容器注入对象
@Autowired
private UserService userService;IOC 容器体系
BeanFactory(顶层接口)
└── ApplicationContext(增强接口)
├── ClassPathXmlApplicationContext(XML配置)
├── AnnotationConfigApplicationContext(注解配置)
└── WebApplicationContext(Web环境)BeanFactory vs ApplicationContext
| 特性 | BeanFactory | ApplicationContext |
|---|---|---|
| 初始化时机 | 懒加载(首次使用时) | 预加载(容器启动时) |
| 国际化 | 不支持 | 支持 |
| 事件机制 | 不支持 | 支持 |
| AOP 支持 | 需手动配置 | 自动支持 |
| 适用场景 | 资源受限环境 | 企业级应用 |
Bean 生命周期
完整生命周期流程
1. 实例化(Instantiation)
↓
2. 属性赋值(Populate)
↓
3. 初始化前(BeanPostProcessor.postProcessBeforeInitialization)
↓
4. 初始化(InitializingBean.afterPropertiesSet、init-method)
↓
5. 初始化后(BeanPostProcessor.postProcessAfterInitialization)
↓
6. 使用中
↓
7. 销毁前(DestructionAwareBeanPostProcessor.postProcessBeforeDestruction)
↓
8. 销毁(DisposableBean.destroy、destroy-method)详细流程图
┌─────────────────────────────────────────────────────────────┐
│ Spring 容器启动 │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 1. 实例化 Bean │
│ - 调用构造函数 │
│ - InstantiationAwareBeanPostProcessor.postProcessBefore │
│ Instantiation(实例化前) │
│ - InstantiationAwareBeanPostProcessor.postProcessAfter │
│ Instantiation(实例化后) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 2. 属性赋值 │
│ - 依赖注入(@Autowired、@Value) │
│ - InstantiationAwareBeanPostProcessor.postProcess │
│ Properties(属性处理) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 3. 初始化前处理 │
│ - BeanNameAware.setBeanName() │
│ - BeanClassLoaderAware.setBeanClassLoader() │
│ - BeanFactoryAware.setBeanFactory() │
│ - ApplicationContextAware.setApplicationContext() │
│ - BeanPostProcessor.postProcessBeforeInitialization() │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 4. 初始化 │
│ - @PostConstruct │
│ - InitializingBean.afterPropertiesSet() │
│ - 自定义 init-method │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 5. 初始化后处理 │
│ - BeanPostProcessor.postProcessAfterInitialization() │
│ - 此处生成 AOP 代理 │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 6. Bean 就绪,可使用 │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 7. 销毁前处理 │
│ - DestructionAwareBeanPostProcessor │
│ .postProcessBeforeDestruction() │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 8. 销毁 │
│ - @PreDestroy │
│ - DisposableBean.destroy() │
│ - 自定义 destroy-method │
└─────────────────────────────────────────────────────────────┘代码示例
@Component
public class MyBean implements InitializingBean, DisposableBean,
BeanNameAware, ApplicationContextAware {
private String beanName;
private ApplicationContext context;
// 1. 构造函数
public MyBean() {
System.out.println("1. 构造函数");
}
// 2. 依赖注入
@Autowired
public void setOtherBean(OtherBean otherBean) {
System.out.println("2. 属性注入");
}
// 3. Aware 接口回调
@Override
public void setBeanName(String name) {
this.beanName = name;
System.out.println("3. BeanNameAware: " + name);
}
@Override
public void setApplicationContext(ApplicationContext ctx) {
this.context = ctx;
System.out.println("3. ApplicationContextAware");
}
// 4. @PostConstruct
@PostConstruct
public void postConstruct() {
System.out.println("4. @PostConstruct");
}
// 5. InitializingBean
@Override
public void afterPropertiesSet() {
System.out.println("5. InitializingBean.afterPropertiesSet");
}
// 6. 自定义 init-method
public void customInit() {
System.out.println("6. customInit-method");
}
// 业务方法
public void doSomething() {
System.out.println("Bean 使用中...");
}
// 7. @PreDestroy
@PreDestroy
public void preDestroy() {
System.out.println("7. @PreDestroy");
}
// 8. DisposableBean
@Override
public void destroy() {
System.out.println("8. DisposableBean.destroy");
}
// 9. 自定义 destroy-method
public void customDestroy() {
System.out.println("9. customDestroy-method");
}
}BeanPostProcessor
作用
BeanPostProcessor 是 Spring 提供的扩展点,可以在 Bean 初始化前后进行自定义处理。
public interface BeanPostProcessor {
// 初始化前
default Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
// 初始化后
default Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}常见实现
| BeanPostProcessor | 作用 |
|---|---|
AutowiredAnnotationBeanPostProcessor | 处理 @Autowired 注入 |
CommonAnnotationBeanPostProcessor | 处理 @Resource、@PostConstruct、@PreDestroy |
ApplicationContextAwareProcessor | 处理 Aware 接口 |
AbstractAutoProxyCreator | AOP 代理创建 |
自定义 BeanPostProcessor
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
if (bean instanceof MyBean) {
System.out.println("初始化前处理: " + beanName);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean instanceof MyBean) {
System.out.println("初始化后处理: " + beanName);
// 可以返回代理对象
}
return bean;
}
}Bean 的作用域
| 作用域 | 说明 | 适用场景 |
|---|---|---|
| singleton(默认) | 单例,整个容器只有一个实例 | 无状态 Bean |
| prototype | 原型,每次获取创建新实例 | 有状态 Bean |
| request | 每个 HTTP 请求一个实例 | Web 应用 |
| session | 每个 HTTP Session 一个实例 | Web 应用 |
| application | 整个 ServletContext 一个实例 | Web 应用 |
@Component
@Scope("prototype")
public class PrototypeBean {
// 每次获取都创建新实例
}面试高频问题
Q1: Spring Bean 的完整生命周期?
回答要点:
- 实例化:调用构造函数
- 属性赋值:依赖注入
- Aware 接口回调:注入容器相关信息
- 初始化前:BeanPostProcessor.postProcessBeforeInitialization
- 初始化:@PostConstruct → InitializingBean → init-method
- 初始化后:BeanPostProcessor.postProcessAfterInitialization(AOP 代理在此生成)
- 使用
- 销毁前:DestructionAwareBeanPostProcessor
- 销毁:@PreDestroy → DisposableBean → destroy-method
Q2: BeanPostProcessor 和 InstantiationAwareBeanPostProcessor 的区别?
| 接口 | 作用时机 | 用途 |
|---|---|---|
| BeanPostProcessor | 初始化前后 | 属性修改、代理创建 |
| InstantiationAwareBeanPostProcessor | 实例化前后 | 控制实例化过程、属性注入 |
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
// 实例化前(可以返回代理对象,跳过实例化)
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
return null;
}
// 实例化后(决定是否进行属性注入)
default boolean postProcessAfterInstantiation(Object bean, String beanName) {
return true;
}
// 属性注入时
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
return pvs;
}
}Q3: Spring 如何解决循环依赖?
回答要点:
- 构造器循环依赖:无法解决,抛出 BeanCurrentlyInCreationException
- Setter 循环依赖:通过三级缓存解决
- Prototype 循环依赖:无法解决
三级缓存:
// 一级缓存:完整的 Bean
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
// 二级缓存:早期暴露的 Bean(未完成属性注入)
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
// 三级缓存:Bean 工厂(用于生成早期 Bean 或代理)
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);流程:
- 创建 A,暴露到三级缓存
- 注入 B,发现 B 未创建
- 创建 B,注入 A
- 从三级缓存获取 A(或其代理),放入二级缓存
- B 完成创建
- A 完成创建
Q4: 为什么三级缓存而不是两级?
关键:AOP 代理的创建时机
- 如果只有两级缓存,需要在暴露早期引用时就确定是否需要代理
- 三级缓存通过 ObjectFactory 延迟决定,只有在真正需要时才创建代理
// 三级缓存存储的是工厂,可以延迟创建代理
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}Q5: singleton Bean 是线程安全的吗?
回答:不是!
- Spring Bean 默认是单例,但 Spring 不保证线程安全
- 如果 Bean 有可变状态,需要自行处理线程安全
解决方案:
// 1. 无状态 Bean(推荐)
@Component
public class StatelessService {
// 无成员变量,线程安全
public String process(String input) {
return input.toUpperCase();
}
}
// 2. 使用 ThreadLocal
@Component
public class StatefulService {
private ThreadLocal<String> state = new ThreadLocal<>();
}
// 3. 改用 prototype 作用域
@Component
@Scope("prototype")
public class PrototypeBean {
private String state; // 每个线程独立实例
}
// 4. 同步控制
@Component
public class SynchronizedService {
private String state;
public synchronized void setState(String state) {
this.state = state;
}
}总结
Bean 生命周期核心要点:
1. 实例化 → 属性注入 → 初始化 → 使用 → 销毁
2. BeanPostProcessor 在初始化前后介入
3. AOP 代理在初始化后生成
4. 循环依赖通过三级缓存解决
5. 单例 Bean 不保证线程安全