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:

  1. 创建A实例,放入三级缓存
  2. A进行属性注入,发现需要B
  3. 创建B实例,放入三级缓存
  4. B进行属性注入,发现需要A
  5. 从三级缓存获取A的早期引用,注入给B
  6. B完成初始化,放入一级缓存
  7. 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生命周期是解决复杂依赖问题、进行高级定制的基础。掌握生命周期各个阶段的特性,能够让我们在框架使用上游刃有余。

版权声明 ▶ 本网站名称:黄磊的博客
▶ 本文标题:Spring Bean生命周期深度剖析:从创建到销毁的完整掌控
▶ 本文链接:https://www.huangleicole.com/backend-related/36.html
▶ 转载本站文章需要遵守:商业转载请联系站长,非商业转载请注明出处!!

如果觉得我的文章对你有用,请随意赞赏