2023.11.13 Spring Bean 的生命周期

目录

Spring 执行流程

Bean 的生命周期 

五个阶段

深入理解 Bean 初始化

实例理解 

总结梳理

经典面试题 


Spring 执行流程

Bean 的生命周期 

  • Spring 中 Bean 的生命周就是 Bean 在 Spring 中从创建到销毁的整个过程


五个阶段

1. 实例化 Bean

  • 为 Bean 对象分配内存空间

2. 设置属性

  • Spring 通过反射机制给 Bean 的属性赋值

3. Bean 初始化

  • 各种通知
  • 初始化前置方法
  • 初始化方法
  • 初始化后置方法

4. 使用 Bean

5. 销毁 Bean


深入理解 Bean 初始化

各种通知接口方法

  • BeanNameAware:允许 Bean 获取自己在容器中的名称
  • BeanFactoryAware:允许 Bean 获取对 Beanfactory的引用
  • ApplicationContextAware:允许 Bean 获取对 ApplicationContext 的引用

初始化前置方法

  • 该方法可以用于执行一些预处理操作,例如 设置一些默认属性或检查依赖关系

初始化方法

  • 如果使用注解方式,可以使用 @PostConstruct 注解来标记初始化方法
  • 如果使用 XML 配置方式,可以在 <bean> 标签中使用 init-method 属性来指定初始化方法的名称

初始化后置方法

  • 该方法可以用于执行一些后续操作,例如资源清理、启动定时任务等

注意:

  • 实例化和初始化是两个完全不同的过程
  • 实例化只是给Bean对象分配内存空间
  • 初始化则是将程序执行权从系统级别转到用户级别,执行用户添加的业务代码

实例理解 

  • 创建一个 BeanComponent 类

  • 在 Spring-config.xml 中使用 <bean> 标签将 BeanComponent 类的 Bean 对象注入到Spring 容器中

  •  BeanComponent 类设置 BeanNameAware 通知、两种初始化方法、销毁时执行的方法
  • sayHi 方法的创建是为了 使用 Bean 对象
import org.springframework.beans.factory.BeanNameAware;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

public class BeanComponent implements BeanNameAware {
    @Override
    public void setBeanName(String s) {
        System.out.println( "BeanName ——> " + s + " 执行了通知");
    }

    /*
    * xml 方式的初始化方法
    * */
    public void myInit() {
        System.out.println("XML 方式的初始化方法");
    }

    @PostConstruct
    public void doPostConstruct() {
        System.out.println("注解方式的初始化方法");
    }

    public void sayHi() {
        System.out.println("执行 sayHi 方法");
    }
    
    /*
    * 销毁时执行的方法
    * 此处使用注解的方式
    * */
    @PreDestroy
    public void doPreDestroy() {
        System.out.println("销毁时的方法 已执行");
    }
}

注意:

  • 在启动类中获取 BeanComponent 类的 Bean 对象,并调用其 sayHi 方法,最后销毁容器
import com.java.demo.component.BeanComponent;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
//        因为 ApplicationContext 中没有销毁方法,所以此处使用 ClassPathXmlApplicationContext
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("Spring-config.xml");
        BeanComponent beanComponent = context.getBean("beanComponent",BeanComponent.class);
//        调用 sayHi 方法,即使用该 Bean 对象
        beanComponent.sayHi();
//        将容器销毁
        context.destroy();
    }
}

运行结果:

  • 我们发现该执行结果,正好与我们的预期相符合

总结梳理

  • Spring 执行流程和 Bean 的生命周期 结合理解

  • 加载配置文件:Spring 容器会先加载配置文件,例如 XML 文件或注解配置,以获取Bean 的定义和相关的配置信息
  • 创建容器:根据配置文件中的定义,Spring 容器会创建一个应用上下文,也就是容器对象,用于管理 Bean 的生命周期
  • 实例化 Bean:Spring 容器根据配置文件中的定义,实例化 Bean 对象,这是通过调用Bean 的构造函数来完成的
  • 设置 Bean 属性:一旦 Bean 实例化完成,Spring 容器会通过调用 Bean 的 setter 方法或直接访问其字段,将文件中定义的属性值注入到 Bean 中
  • 调用 Bean 的初始化方法:如果 Bean 实现了 InitializingBean 接口,Spring 容器会在属性注入完成后调用其定义的初始化方法。同时如果在配置文件中指定了自定义的初始化方法。Spring 容器也会调用该方法
  • 使用 Bean:在 Bean 的初始化完成后,Spring 容器会将其放入容器中,供其他 Bean 或应用程序使用
  • 调用 Bean 的销毁方法:当 Spring 容器关闭时,它会销毁之前先释放的 Bean 资源,如果 Bean 实现了 DisposableBean 接口,容器会在销毁前调用其定义的销毁方法。同时,如果在配置文件中指定了自定义的销毁方法,Spring 容器也会调用该方法

经典面试题 

是否可以先 执行初始化 再 执行设置属性 ?

  • 不可以
  • 因为初始化方法中可能会用到设置后的属性

实例理解

@Controller
public class StudentController {
 
    //属性注入
    @Autowired
    private Student student;
 
    //初始化
    @PostConstruct
    public void init() {
        student.setName("xiaolin");
    }
 
}
  • 如果此时先执行了初始化 init 方法
  • init 方法中需要使用属性注入后得到的 student 对象
  • 此时该 student 对象还未被 Spring 容器注入便被 init 方法进行修改
  • 上述过程,将直接引发空指针异常
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

茂大师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值