Spring Bean生命周期源码深度解析

一、Bean生命周期全景图

在深入细节之前,先了解Spring Bean生命周期的完整流程:


二、Bean的生成过程

1. 生成BeanDefinition:Spring扫描的底层实现

Spring启动时首先会扫描配置的包路径,将符合条件的类转换为BeanDefinition对象。

扫描流程图

1.1 扫描流程详解
复制代码
// 核心扫描方法:ClassPathScanningCandidateComponentProvider.scanCandidateComponents()
public Set<BeanDefinition> scanCandidateComponents(String basePackage) {
    Set<BeanDefinition> candidates = new LinkedHashSet<>();
    
    // 1. 获取包路径下所有.class文件的Resource对象
    Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
    
    for (Resource resource : resources) {
        // 2. 使用MetadataReaderFactory解析Resource
        MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
        
        // 3. 使用过滤器进行筛选
        if (isCandidateComponent(metadataReader)) {
            // 4. 生成ScannedGenericBeanDefinition
            ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
            sbd.setResource(resource);
            sbd.setSource(resource);
            
            // 5. 检查是否为接口/抽象类
            if (isCandidateComponent(sbd)) {
                candidates.add(sbd);
            }
        }
    }
    return candidates;
}
1.2 MetadataReader:类元数据读取器

Spring使用ASM技术读取类字节码,避免过早加载类到JVM。

复制代码
// MetadataReader的主要功能
public interface MetadataReader {
    ClassMetadata getClassMetadata();      // 类信息
    AnnotationMetadata getAnnotationMetadata();  // 注解信息
    Resource getResource();                // 资源信息
}

// 使用示例
SimpleMetadataReaderFactory factory = new SimpleMetadataReaderFactory();
MetadataReader reader = factory.getMetadataReader("com.service.UserService");

// 获取类信息
ClassMetadata classMetadata = reader.getClassMetadata();
System.out.println(classMetadata.getClassName());      // 类名
System.out.println(classMetadata.isInterface());       // 是否接口
System.out.println(classMetadata.isAbstract());        // 是否抽象类

// 获取注解信息
AnnotationMetadata annotationMetadata = reader.getAnnotationMetadata();
Set<String> annotationTypes = annotationMetadata.getAnnotationTypes();  // 所有注解
1.3 筛选机制

扫描过程中会进行多级筛选:

  1. excludeFilters:排除过滤器

  2. includeFilters:包含过滤器

  3. 条件注解@Conditional注解的条件匹配

1.4 BeanDefinition的多种来源

除了扫描,BeanDefinition还可以来自:

  • XML配置的<bean>标签

  • @Bean注解的方法

  • 编程式注册

2. 合并BeanDefinition:处理父子关系

Spring支持父子BeanDefinition,类似但不同于Java的继承。

复制代码
<!-- 父BeanDefinition -->
<bean id="parent" class="com.service.Parent" scope="prototype"/>

<!-- 子BeanDefinition,继承父的scope属性 -->
<bean id="child" class="com.service.Child" parent="parent"/>

子BeanDefinition会继承父BeanDefinition的属性,在创建Bean前需要进行合并,得到完整的BeanDefinition。

3. 加载类:按需加载到JVM

复制代码
// AbstractAutowireCapableBeanFactory中的加载逻辑
protected Class<?> resolveBeanClass(RootBeanDefinition mbd, String beanName) throws ClassNotFoundException {
    // 1. 检查是否已加载
    if (mbd.hasBeanClass()) {
        return mbd.getBeanClass();
    }
    
    // 2. 使用类加载器加载
    return doResolveBeanClass(mbd, typesToMatch);
}

类加载器选择顺序

  1. 当前线程的ClassLoader

  2. ClassUtils类的ClassLoader

  3. 系统类加载器

4. 实例化前:第一个关键扩展点

复制代码
@Component
public class CustomInstantiationAwareBeanPostProcessor 
    implements InstantiationAwareBeanPostProcessor {
    
    @Override
    public Object postProcessBeforeInstantiation(
        Class<?> beanClass, String beanName) throws BeansException {
        
        if ("userService".equals(beanName)) {
            System.out.println("实例化前扩展点");
            
            // 如果返回非null对象,Spring将跳过后续步骤
            // return new UserService();
        }
        return null;  // 返回null让Spring继续正常流程
    }
}

重要特性:如果此方法返回非null对象,Spring将跳过:

  • 正常实例化

  • 依赖注入

  • 直接执行初始化后步骤

5. 实例化:三种创建对象的方式

5.1 Supplier方式(编程式)
复制代码
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder
    .genericBeanDefinition()
    .getBeanDefinition();

// 设置Supplier
beanDefinition.setInstanceSupplier(new Supplier<Object>() {
    @Override
    public Object get() {
        return new UserService();
    }
});

context.registerBeanDefinition("userService", beanDefinition);
5.2 工厂方法方式

静态工厂方法

复制代码
<bean id="userService" class="com.service.UserService" 
      factory-method="createUserService"/>
复制代码
public class UserService {
    public static UserService createUserService() {
        return new UserService();
    }
}

实例工厂方法

复制代码
<bean id="commonService" class="com.service.CommonService"/>
<bean id="userService" factory-bean="commonService" 
      factory-method="createUserService"/>
复制代码
public class CommonService {
    public UserService createUserService() {
        return new UserService();
    }
}
5.3 推断构造方法

Spring会根据以下规则选择构造方法:

  1. 只有一个构造方法 → 使用该构造方法

  2. 多个构造方法且存在无参构造 → 使用无参构造

  3. 多个构造方法且指定了@Autowired → 使用指定构造方法

@Lookup注解的特殊处理

复制代码
@Component
public class UserService {
    
    @Lookup("orderService")
    public OrderService createOrderService() {
        return null;  // Spring会生成代理方法
    }
}

如果存在@Lookup注解的方法,Spring会生成代理对象而非直接实例化。

6. BeanDefinition的后置处理

复制代码
@Component
public class CustomMergedBeanDefinitionPostProcessor 
    implements MergedBeanDefinitionPostProcessor {
    
    @Override
    public void postProcessMergedBeanDefinition(
        RootBeanDefinition beanDefinition, 
        Class<?> beanType, 
        String beanName) {
        
        if ("userService".equals(beanName)) {
            // 修改BeanDefinition
            beanDefinition.getPropertyValues()
                .add("orderService", new OrderService());
        }
    }
}

Spring内置实现AutowiredAnnotationBeanPostProcessor在此阶段查找注入点并缓存。

7. 实例化后:第三个扩展点

复制代码
@Component
public class CustomInstantiationAwareBeanPostProcessor 
    implements InstantiationAwareBeanPostProcessor {
    
    @Override
    public boolean postProcessAfterInstantiation(
        Object bean, String beanName) throws BeansException {
        
        if ("userService".equals(beanName)) {
            UserService userService = (UserService) bean;
            userService.test();
        }
        return true;  // 返回false将阻止属性填充
    }
}

8. 自动注入与属性处理

此阶段处理@Autowired@Resource@Value等注解。

复制代码
@Component
public class CustomInstantiationAwareBeanPostProcessor 
    implements InstantiationAwareBeanPostProcessor {
    
    @Override
    public PropertyValues postProcessProperties(
        PropertyValues pvs, Object bean, String beanName) throws BeansException {
        
        if ("userService".equals(beanName)) {
            for (Field field : bean.getClass().getDeclaredFields()) {
                if (field.isAnnotationPresent(CustomInject.class)) {
                    field.setAccessible(true);
                    try {
                        field.set(bean, "注入的值");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return pvs;
    }
}

9. Aware接口回调

复制代码
@Component
public class UserService implements 
    BeanNameAware, 
    BeanFactoryAware, 
    BeanClassLoaderAware {
    
    @Override
    public void setBeanName(String name) {
        System.out.println("Bean名称:" + name);
    }
    
    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        System.out.println("BeanFactory:" + beanFactory);
    }
    
    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("ClassLoader:" + classLoader);
    }
}

10. 初始化前:第四个扩展点

复制代码
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
    
    @Override
    public Object postProcessBeforeInitialization(
        Object bean, String beanName) throws BeansException {
        
        if ("userService".equals(beanName)) {
            System.out.println("初始化前处理");
        }
        return bean;
    }
}

Spring内置处理器在此阶段的工作

  1. InitDestroyAnnotationBeanPostProcessor:执行@PostConstruct方法

  2. ApplicationContextAwareProcessor:处理其他Aware接口回调

11. 初始化:执行初始化逻辑

复制代码
@Component
public class UserService implements InitializingBean {
    
    private void customInit() {
        System.out.println("自定义初始化方法");
    }
    
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean.afterPropertiesSet()");
    }
}

两种初始化方式

  1. 实现InitializingBean接口的afterPropertiesSet()方法

  2. BeanDefinition中指定的初始化方法

12. 初始化后:最后一个扩展点

复制代码
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
    
    @Override
    public Object postProcessAfterInitialization(
        Object bean, String beanName) throws BeansException {
        
        if ("userService".equals(beanName)) {
            System.out.println("初始化后处理");
            // 可以返回代理对象
        }
        return bean;
    }
}

重要:Spring AOP就是基于此扩展点实现的,返回的可能是代理对象而非原始对象。


三、Bean的销毁过程

1. 容器关闭触发销毁

复制代码
AnnotationConfigApplicationContext context = 
    new AnnotationConfigApplicationContext(AppConfig.class);
    
// 使用Bean...
UserService userService = context.getBean(UserService.class);
userService.test();

// 关闭容器,触发Bean销毁
context.close();

2. 判断是否为DisposableBean

在Bean创建的最后阶段(初始化后),Spring会判断Bean是否需要销毁:

复制代码
// 判断逻辑
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
    // 1. 是否为原型Bean(原型Bean不管理销毁)
    if (mbd.isPrototype()) {
        return;
    }
    
    // 2. 检查是否实现了DisposableBean或AutoCloseable接口
    boolean implementsDisposableBean = (bean instanceof DisposableBean);
    boolean implementsAutoCloseable = (bean instanceof AutoCloseable);
    
    // 3. 检查是否有destroyMethod
    String destroyMethodName = mbd.getDestroyMethodName();
    
    // 4. 检查DestructionAwareBeanPostProcessor
    boolean hasDestructionAwareBeanPostProcessors = 
        hasDestructionAwareBeanPostProcessors();
    
    if (implementsDisposableBean || implementsAutoCloseable || 
        destroyMethodName != null || hasDestructionAwareBeanPostProcessors) {
        
        // 适配为DisposableBeanAdapter并注册
        registerDisposableBean(beanName, 
            new DisposableBeanAdapter(bean, beanName, mbd, 
                getBeanPostProcessors(), getAccessControlContext()));
    }
}

3. 适配器模式的应用

由于销毁方式多样,Spring使用DisposableBeanAdapter进行统一适配:

复制代码
// DisposableBeanAdapter统一处理各种销毁方式
class DisposableBeanAdapter implements DisposableBean {
    
    private final Object bean;
    private final String beanName;
    private final RootBeanDefinition beanDefinition;
    
    @Override
    public void destroy() throws Exception {
        // 1. 调用DestructionAwareBeanPostProcessor
        // 2. 调用DisposableBean.destroy()
        // 3. 调用AutoCloseable.close()
        // 4. 调用自定义destroy-method
    }
}

4. 销毁执行流程

复制代码
// DefaultSingletonBeanRegistry.destroySingletons()
public void destroySingletons() {
    // 1. 发布ContextClosedEvent事件
    publishEvent(new ContextClosedEvent(this));
    
    // 2. 调用LifecycleProcessor的onClose()
    getLifecycleProcessor().onClose();
    
    // 3. 销毁单例Bean
    synchronized (this.singletonObjects) {
        // 遍历所有需要销毁的Bean
        for (String beanName : disposableBeans.keySet()) {
            DisposableBean disposableBean = disposableBeans.remove(beanName);
            
            try {
                // 从单例池移除
                removeSingleton(beanName);
                
                // 调用销毁方法
                disposableBean.destroy();
                
                // 处理依赖此Bean的其他Bean
                destroySingleton(beanName);
                
                // 处理内部Bean
                destroyBean(beanName, disposableBean, null);
            } catch (Exception e) {
                logger.error("销毁Bean失败: " + beanName, e);
            }
        }
        
        // 清理缓存
        clearSingletonCache();
    }
}

5. 多种销毁方式示例

5.1 实现DisposableBean接口
复制代码
@Component
public class UserService implements DisposableBean {
    
    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean.destroy()被调用");
        // 释放资源
    }
}
5.2 实现AutoCloseable接口
复制代码
@Component  
public class DataSourceService implements AutoCloseable {
    
    @Override
    public void close() throws Exception {
        System.out.println("AutoCloseable.close()被调用");
        // 关闭连接
    }
}
5.3 指定destroy-method
复制代码
<bean id="userService" class="com.service.UserService" 
      destroy-method="cleanup"/>
复制代码
public class UserService {
    public void cleanup() {
        System.out.println("自定义销毁方法被调用");
    }
}
5.4 使用@PreDestroy注解
复制代码
@Component
public class UserService {
    
    @PreDestroy
    public void preDestroy() {
        System.out.println("@PreDestroy方法被调用");
    }
}

6. 销毁过程中的依赖处理

如果Bean A依赖Bean B,当Bean B被销毁时:

  1. 检查Bean A是否也依赖Bean B

  2. 如果依赖,则Bean A也需要被销毁

  3. 递归处理所有依赖关系


四、完整生命周期总结

BeanPostProcessor执行顺序总结

  1. InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() - 实例化前

  2. 构造方法实例化 - 创建对象

  3. MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition() - 处理BeanDefinition

  4. InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() - 实例化后

  5. 自动注入 - 处理依赖关系

  6. InstantiationAwareBeanPostProcessor.postProcessProperties() - 属性处理

  7. Aware接口回调 - BeanNameAware、BeanFactoryAware等

  8. BeanPostProcessor.postProcessBeforeInitialization() - 初始化前

  9. 初始化 - InitializingBean.afterPropertiesSet()和init-method

  10. BeanPostProcessor.postProcessAfterInitialization() - 初始化后

设计模式应用总结

  1. 模板方法模式:Bean创建流程的固定骨架

  2. 策略模式:多种实例化方式(Supplier、工厂方法、构造方法)

  3. 适配器模式:DisposableBeanAdapter统一各种销毁方式

  4. 观察者模式:事件发布与监听

  5. 工厂模式:BeanFactory创建和管理Bean


五、性能优化与最佳实践

1. 使用ASM避免类加载

复制代码
// Spring使用ASM读取类元数据,避免启动时加载所有类
MetadataReader reader = metadataReaderFactory.getMetadataReader(className);
// 仅读取字节码,不加载到JVM

2. 合理使用扩展点

  • InstantiationAwareBeanPostProcessor:控制实例化过程

  • MergedBeanDefinitionPostProcessor:修改BeanDefinition

  • BeanPostProcessor:在初始化前后添加逻辑

3. 避免循环依赖

  • 使用setter注入而非构造器注入

  • 使用@Lazy注解延迟加载

  • 重新设计代码结构

4. 合理配置Bean作用域

  • 无状态Bean使用单例(默认)

  • 有状态Bean考虑使用原型

  • Web环境注意request、session作用域


六、调试与监控技巧

1. 使用JFR监控Bean生命周期

复制代码
# 启动应用时添加JFR参数
java -XX:+FlightRecorder -XX:StartFlightRecording=duration=60s,filename=recording.jfr -jar app.jar

2. 添加自定义监控

复制代码
@Component
public class BeanLifecycleMonitor implements BeanPostProcessor {
    
    private Map<String, Long> creationTimes = new ConcurrentHashMap<>();
    
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        creationTimes.put(beanName, System.currentTimeMillis());
        return bean;
    }
    
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        Long startTime = creationTimes.get(beanName);
        if (startTime != null) {
            long duration = System.currentTimeMillis() - startTime;
            System.out.println(beanName + " 创建耗时: " + duration + "ms");
        }
        return bean;
    }
}

七、常见问题与解决方案

Q1: Bean创建过程卡住怎么办?

排查步骤

  1. 检查postProcessBeforeInstantiation()是否返回了对象

  2. 检查循环依赖

  3. 检查@DependsOn注解的依赖关系

  4. 使用线程转储分析

Q2: 销毁方法未执行?

可能原因

  1. Bean是原型作用域(Spring不管理原型Bean的销毁)

  2. 容器未正常关闭

  3. 销毁方法抛出了异常

Q3: 如何优雅地关闭Spring容器?

复制代码
// 1. 注册Shutdown Hook
context.registerShutdownHook();

// 2. 编程式关闭
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
    context.close();
}));

八、总结

Spring Bean的生命周期是一个精心设计的过程,包含了多个扩展点和回调机制。理解这个过程对于:

  1. 深度使用Spring框架:掌握各个扩展点的作用

  2. 排查复杂问题:快速定位Bean创建、初始化、销毁过程中的问题

  3. 性能优化:合理配置Bean,避免不必要的开销

  4. 框架扩展:基于Spring的扩展机制开发自己的功能

相关推荐
SunnyDays10111 小时前
Java 高效实现 CSV 转 PDF
java·csv转pdf
隐形喷火龙1 小时前
SpringBoot 异步任务持久化方案:崩溃重启不丢任务的完整实现
java·spring boot·后端
我是koten1 小时前
K8s启动pod失败,日志报非法的Jar包排查思路(Invalid or corrupt jarfile /app/xxxx,jar)
java·docker·容器·kubernetes·bash·jar·shell
、BeYourself1 小时前
PGvector :在 Spring AI 中实现向量数据库存储与相似性搜索
数据库·人工智能·spring·springai
WX-bisheyuange1 小时前
基于Spring Boot的库存管理系统的设计与实现
java·spring boot·后端
明天好,会的1 小时前
分形生成实验(三):Rust强类型驱动的后端分步实现与编译时契约
开发语言·人工智能·后端·rust
YanDDDeat1 小时前
【JVM】类初始化和加载
java·开发语言·jvm·后端
码农水水1 小时前
阿里Java面试被问:单元测试的最佳实践
java·面试·单元测试
indexsunny1 小时前
互联网大厂Java面试实战:Spring Cloud微服务与Redis缓存在电商场景中的应用
java·spring boot·redis·spring cloud·微服务·消息队列·电商
hunter14501 小时前
2026.1.4 html简单制作
java·前端·笔记·html