分析 Bean 初始化过程

举报
developer_Li 发表于 2025/04/21 16:21:28 2025/04/21
【摘要】 Spring Bean 的初始化过程是 Spring 容器在启动时注册、创建和配置 Bean 的一系列步骤,涉及 BeanDefinition 解析、依赖注入、生命周期回调 等。详细拆解 Spring Bean 初始化的完整流程: 1. BeanDefinition 解析Spring 容器在启动时,首先 扫描 @Component、@Service、@Repository 等注解的类。通过 ...

Spring Bean 的初始化过程是 Spring 容器在启动时注册、创建和配置 Bean 的一系列步骤,涉及 BeanDefinition 解析、依赖注入、生命周期回调 等。

详细拆解 Spring Bean 初始化的完整流程

1. BeanDefinition 解析

  • Spring 容器在启动时,首先 扫描 @Component@Service@Repository 等注解的类

  • 通过 BeanDefinitionRegistry 注册 BeanDefinition(只是定义 Bean,未实例化)。

  • 如果使用 XML 配置,则从 applicationContext.xml 解析 Bean 结构。

示例:

xml中
<bean id="myBean" class="com.example.MyBean"/>

 这一步只是定义 Bean,不会真正创建对象!

2. BeanFactory 准备 & 创建 Bean

Spring 解析所有 BeanDefinition 之后,进入 BeanFactory 阶段:

  1. 创建单例 Bean(如果 @Scope("singleton"))。

  2. 检查 Bean 依赖项@Autowired@Qualifier)。

  3. 构造方法执行(调用 new MyBean()

3. 属性填充(依赖注入)

  • Spring 解析 @Autowired 依赖,并将对应 Bean 注入字段:

@Component
public class MyBean {
    @Autowired
    private AnotherBean anotherBean;
}
  • 如果 Bean 有 setter 方法,Spring 会调用 setXxx() 进行填充。

此时 Bean 还没有调用 @PostConstruct,生命周期未完成!

4. 调用 InitializingBean.afterPropertiesSet()

如果 Bean 实现了 InitializingBean,Spring 会执行 afterPropertiesSet()

@Component
public class MyBean implements InitializingBean {
    @Override
    public void afterPropertiesSet() {
        System.out.println("Bean 初始化完成!");
    }
}

可用于 Bean 初始化后的额外操作,如连接池初始化、任务调度等。

5. 调用 @PostConstruct

如果 Bean @PostConstruct 方法,Spring 会执行:

@PostConstruct
public void init() {
    System.out.println("Bean 已完全初始化!");
}

相比 afterPropertiesSet()@PostConstruct 更推荐在 Spring Boot 项目中使用

6. Bean 进入 Spring 容器

  •  所有依赖注入 & 初始化逻辑完成后,Bean 被缓存到 DefaultSingletonBeanRegistry
  • 单例 Bean 会一直存在,直到容器销毁

7. Bean 销毁(@PreDestroyDisposableBean.destroy()

如果 Bean 需要释放资源(如关闭数据库连接),Spring 在容器关闭时执行销毁逻辑

@PreDestroy
public void cleanup() {
    System.out.println("Bean 即将销毁!");
}

总结

  • BeanDefinition 解析 → BeanFactory 创建 → 依赖注入 → afterPropertiesSet()@PostConstruct → Bean 可用 → 销毁
  •  @Autowired 在 Bean 创建后执行,但 @PostConstruct 在 Bean 可用后执行
  • 单例 Bean 存在于 DefaultSingletonBeanRegistry,而原型 Bean每次 getBean() 时都会创建新对象

注意事项:

  • @Component
    public class CustomBeanPostProcessor implements BeanPostProcessor {
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) {
            System.out.println(beanName + " 初始化前执行");
            return bean;
        }
    
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) {
            System.out.println(beanName + " 初始化后执行");
            return bean;
        }
    }
    

    适用于调试 Bean 初始化前后的行为。

  • 如果 Bean 代理(如 @Transactional)怎么办?
    • 如果 Bean 被 Spring 代理(例如使用 @Transactional@Async),它的实际初始化过程 可能额外包含 CGLIB 或 JDK 动态代理:
      @Service
      @Transactional
      public class MyTransactionalService {
      }
      

      Spring 可能会在初始化阶段使用 CGLIB 生成代理对象,导致 postProcessBeforeInitialization() 里获取的 Bean 不是原始类。验证 Bean 是否被代理:

      System.out.println(AopUtils.isCglibProxy(myBean)); // true 代表是 CGLIB 代理
  • Spring Bean 初始化流程如下:
    1. 实例化 Bean(执行 new MyBean()
    2. postProcessBeforeInstantiation(创建前处理)
    3. 执行构造方法,创建 Bean 实例
    4. postProcessProperties(属性注入前处理)
    5. Spring 进行依赖注入(如 @Autowired 字段填充)
    6. postProcessBeforeInitialization(初始化前处理)
    7. 执行 @PostConstructInitializingBean.afterPropertiesSet()
    8. Bean 进入 Spring 容器,可供使用
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。