spring学习笔记(四)我对spring中bean生命周期的理解

简介: spring学习笔记(四)我对spring中bean生命周期的理解

我们先看一下spring中bean的生命周期:

image.png


这是我在网上随便找的一张图,大家估计也看得不少,接下来我就这张图一步步分析spring为什么会这么设计bean的生命周期。


首先,我们知道spring的一大亮点就是IOC(控制反转)跟DI(依赖注入)。对于前两步,实例化对话以及设置对象属性我相信大家都没什么疑问。对应的步骤如下:

  • Bean的建立, 由BeanFactory读取Bean定义文件,并生成各个实例
  • Setter注入,执行Bean的属性依赖注入


后面的步骤,我们可以将其分为三步,


第一步,实现Aware一系列接口唤醒bean自身,使bean能感知到容器的存在。


第二步:初始化bean,这里的初始化是指实现我们自己定义的初始化方法。


第三步:销毁。


很明显,bean核心生命周期就在第二步


我们分析为什么会有第一步?为什么不直接初始化呢?


为了回答这个问题我们要知道,spring与spring所管理的bean默认是无状态的,即bean默认是无法感知到spring容器的。


但是为了实现bean的初始化,我们又不得不拿到容器对象,类似的代码就像这样

/**
 * @Author: dmz
 * @Description:
 * @Date: Create in 23:51 2019/3/18
 */
public class Person implements ApplicationContextAware {
    private ApplicationContext applicationContext;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
    private String name;
    public Person(String name) {
        this.name = name;
    }
}

只有经过上面的步骤,我们的bean才跟spring发生了耦合,这里顺便说一下,spring中的容器有两种,一种是BeanFactory,一种是ApplicationContext。所以我们实现ApplicationContextAware 跟实现BeanFactoryAware的目的是一样,都是为了使bean感知到容器。


我们要知道的是,第一步使bean感知到容器,是为了帮助bean完成接下来的初始化。至于为什么最开始是(BeanNameAware的setBeanName(), 如果实现该接口,则执行其setBeanName方法),我相信这也不难理解,自身的优先级自然是高于容器的,在拿到容器对象前先获取自身Id也是可以理解的


对应步骤为:


  • BeanNameAware的setBeanName(), 如果实现该接口,则执行其setBeanName方法
  • BeanFactoryAware的setBeanFactory(),如果实现该接口,则执行其setBeanFactory方法
  • 若有Bean类实现了org.springframework.context.ApplicationContextAware接口,则执行其setApplicationContext()方法


接下来是第二步的分析:第二步可以拆分成三个部分:


1.初始化前:

  • BeanPostProcessor的processBeforeInitialization(),如果有关联的processor,则在Bean初始化之前都会执行这个实例的processBeforeInitialization()方法

2.执行初始化:

  • InitializingBean的afterPropertiesSet(),如果实现了该接口,则执行其afterPropertiesSet()方法
  • Bean定义文件中定义init-method

3.初始化后

  • BeanPostProcessors的processAfterInitialization(),如果有关联的processor,则在Bean初始化之前都会执行这个实例的processAfterInitialization()方法

对于这一步我们应该知道的是,BeanPostProcessor这个接口的作用,是对bean在初始化前后做一些操作


而我们自定义的initMethod方法跟实现InitializingBean,是为了帮助我们对bean进行初始化


最后是第三步:销毁

  • DisposableBean的destroy(),在容器关闭时,如果Bean类实现了该接口,则执行它的destroy()方法
  • Bean定义文件中定义destroy-method,在容器关闭时,可以在Bean定义文件中使用“destory-method”定义的方法

我们一步步分析下来就会发现,每一步的存在都有其合理性,并且顺序上也合理,不能随意打乱


经过这次我也发现,只有真正的理解才能记住,死记是记不住的,平常多调调源码帮助还是很大的。


相关文章
|
20天前
|
XML 安全 Java
|
3天前
|
XML Java 数据格式
Spring容器Bean之XML配置方式
通过对以上内容的掌握,开发人员可以灵活地使用Spring的XML配置方式来管理应用程序的Bean,提高代码的模块化和可维护性。
21 6
|
5天前
|
XML Java 数据格式
🌱 深入Spring的心脏:Bean配置的艺术与实践 🌟
本文深入探讨了Spring框架中Bean配置的奥秘,从基本概念到XML配置文件的使用,再到静态工厂方式实例化Bean的详细步骤,通过实际代码示例帮助读者更好地理解和应用Spring的Bean配置。希望对你的Spring开发之旅有所助益。
33 3
|
1月前
|
缓存 Java Spring
实战指南:四种调整 Spring Bean 初始化顺序的方案
本文探讨了如何调整 Spring Boot 中 Bean 的初始化顺序,以满足业务需求。文章通过四种方案进行了详细分析: 1. **方案一 (@Order)**:通过 `@Order` 注解设置 Bean 的初始化顺序,但发现 `@PostConstruct` 会影响顺序。 2. **方案二 (SmartInitializingSingleton)**:在所有单例 Bean 初始化后执行额外的初始化工作,但无法精确控制特定 Bean 的顺序。 3. **方案三 (@DependsOn)**:通过 `@DependsOn` 注解指定 Bean 之间的依赖关系,成功实现顺序控制,但耦合性较高。
实战指南:四种调整 Spring Bean 初始化顺序的方案
|
18天前
|
安全 Java 开发者
Spring容器中的bean是线程安全的吗?
Spring容器中的bean默认为单例模式,多线程环境下若操作共享成员变量,易引发线程安全问题。Spring未对单例bean做线程安全处理,需开发者自行解决。通常,Spring bean(如Controller、Service、Dao)无状态变化,故多为线程安全。若涉及线程安全问题,可通过编码或设置bean作用域为prototype解决。
28 1
|
1月前
|
前端开发 Java 开发者
Spring生态学习路径与源码深度探讨
【11月更文挑战第13天】Spring框架作为Java企业级开发中的核心框架,其丰富的生态系统和强大的功能吸引了无数开发者的关注。学习Spring生态不仅仅是掌握Spring Framework本身,更需要深入理解其周边组件和工具,以及源码的底层实现逻辑。本文将从Spring生态的学习路径入手,详细探讨如何系统地学习Spring,并深入解析各个重点的底层实现逻辑。
64 9
|
2月前
|
前端开发 Java 数据库
SpringBoot学习
【10月更文挑战第7天】Spring学习
42 9
|
1月前
|
Java Kotlin 索引
学习Spring框架特性及jiar包下载
Spring 5作为最新版本,更新了JDK基线至8,修订了核心框架,增强了反射和接口功能,支持响应式编程及Kotlin语言,引入了函数式Web框架,并提升了测试功能。Spring框架可在其官网下载,包括文档、jar包和XML Schema文档,适用于Java SE和Java EE项目。
33 0
|
2月前
|
Java 测试技术 Windows
咦!Spring容器里为什么没有我需要的Bean?
【10月更文挑战第11天】项目经理给小菜分配了一个紧急需求,小菜迅速搭建了一个SpringBoot项目并完成了开发。然而,启动测试时发现接口404,原因是控制器包不在默认扫描路径下。通过配置`@ComponentScan`的`basePackages`字段,解决了问题。总结:`@SpringBootApplication`默认只扫描当前包下的组件,需要扫描其他包时需配置`@ComponentScan`。
|
2月前
|
XML Java 数据格式
Spring学习
【10月更文挑战第6天】Spring学习
27 1