AI摘要
文章以@PostConstruct空指针为例,剖析Spring Bean生命周期:实例化→属性填充→Aware→BeanPostProcessor→初始化→销毁,结合三级缓存解决循环依赖,并演示自定义BeanPostProcessor与生命周期接口的实战用法。
(一) 从一个诡异的NullPointerException说起
我在开发一个数据同步服务时遇到了一个奇怪的问题:在@PostConstruct方法中调用另一个Bean的方法时抛出了NullPointerException,但那个Bean明明已经通过@Autowired注入了。
@Service
public class DataSyncService {
@Autowired
private UserService userService; // 这里已经注入
@PostConstruct
public void init() {
// 这里userService竟然是null!
userService.someMethod(); // NullPointerException
}
}问题根源: 对Spring Bean生命周期理解不够深入。Bean的创建过程是分阶段的,@PostConstruct执行时,某些依赖可能还没有完全初始化。
(二) Bean生命周期的完整流程
1. Bean创建的核心阶段
实例化 → 属性填充 → Aware接口回调 → BeanPostProcessor前置处理
→ 初始化方法 → BeanPostProcessor后置处理 → 使用中 → 销毁2. 源码级别的阶段分析
// AbstractAutowireCapableBeanFactory.java
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 1. 实例化(通过反射调用构造函数)
BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args);
Object bean = instanceWrapper.getWrappedInstance();
// 2. 属性注入(依赖注入)
populateBean(beanName, mbd, instanceWrapper);
// 3. 初始化
Object exposedObject = initializeBean(beanName, exposedObject, mbd);
return exposedObject;
}
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
// 3.1 调用Aware接口方法
invokeAwareMethods(beanName, bean);
// 3.2 BeanPostProcessor前置处理
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
// 3.3 调用初始化方法
try {
invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable ex) {
throw new BeanCreationException(...);
}
// 3.4 BeanPostProcessor后置处理
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}(三) 实战:自定义Bean生命周期控制
1. 实现完整的生命周期接口
@Component
public class LifecycleDemoBean implements
BeanNameAware, BeanFactoryAware, ApplicationContextAware,
InitializingBean, DisposableBean, SmartInitializingSingleton {
private String beanName;
// 1. BeanNameAware - 设置Bean名称
@Override
public void setBeanName(String name) {
this.beanName = name;
System.out.println("1. BeanNameAware.setBeanName: " + name);
}
// 2. BeanFactoryAware - 设置BeanFactory
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("2. BeanFactoryAware.setBeanFactory");
}
// 3. ApplicationContextAware - 设置ApplicationContext
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("3. ApplicationContextAware.setApplicationContext");
}
// 4. @PostConstruct注解方法
@PostConstruct
public void postConstruct() {
System.out.println("4. @PostConstruct方法执行");
}
// 5. InitializingBean.afterPropertiesSet()
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("5. InitializingBean.afterPropertiesSet()");
}
// 6. 自定义init-method
public void customInit() {
System.out.println("6. 自定义init-method执行");
}
// 7. SmartInitializingSingleton.afterSingletonsInstantiated()
@Override
public void afterSingletonsInstantiated() {
System.out.println("7. 所有单例Bean初始化完成后执行");
}
// 销毁方法执行顺序与初始化相反
@PreDestroy
public void preDestroy() {
System.out.println("8. @PreDestroy方法执行");
}
@Override
public void destroy() throws Exception {
System.out.println("9. DisposableBean.destroy()");
}
public void customDestroy() {
System.out.println("10. 自定义destroy-method执行");
}
}2. 配置类设置
@Configuration
public class LifecycleConfig {
@Bean(initMethod = "customInit", destroyMethod = "customDestroy")
public LifecycleDemoBean lifecycleDemoBean() {
return new LifecycleDemoBean();
}
}(四) 解决循环依赖的底层原理
1. 三级缓存机制
// DefaultSingletonBeanRegistry.java
public class DefaultSingletonBeanRegistry ... {
// 一级缓存:存放完全初始化好的Bean
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
// 二级缓存:存放早期暴露的Bean(未完成属性注入)
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
// 三级缓存:存放Bean工厂,用于解决循环依赖
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 先从一级缓存获取
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 如果正在创建中,尝试从二级缓存获取
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
// 加锁,确保单例
synchronized (this.singletonObjects) {
// 再次检查
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
// 从三级缓存获取ObjectFactory
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
// 移动到二级缓存
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
}2. 循环依赖解决流程
假设A依赖B,B依赖A:
- 创建A实例,放入三级缓存
- A进行属性注入,发现需要B
- 创建B实例,放入三级缓存
- B进行属性注入,发现需要A
- 从三级缓存获取A的早期引用,注入给B
- B完成初始化,放入一级缓存
- A获取到完整的B,完成初始化,放入一级缓存
(五) 高级应用:自定义BeanPostProcessor
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor, Ordered {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof BusinessService) {
System.out.println("BeanPostProcessor前置处理: " + beanName);
// 可以在这里进行代理包装等操作
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof BusinessService) {
System.out.println("BeanPostProcessor后置处理: " + beanName);
// 通常在这里创建AOP代理
return wrapWithProxy(bean);
}
return bean;
}
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE; // 确保最先执行
}
private Object wrapWithProxy(Object bean) {
// 创建动态代理的逻辑
return Proxy.newProxyInstance(
bean.getClass().getClassLoader(),
bean.getClass().getInterfaces(),
(proxy, method, args) -> {
System.out.println("方法拦截: " + method.getName());
return method.invoke(bean, args);
}
);
}
}总结: 深入理解Spring Bean生命周期是解决复杂依赖问题、进行高级定制的基础。掌握生命周期各个阶段的特性,能够让我们在框架使用上游刃有余。