💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
[TOC] # 延迟初始化 当 bean 的作用域为 singleton 时,bean 对象是在 Spring 容器启动时就进行创建了。即默认情况下会在容器启动时初始化 bean. 但我们也可以指定 bean 节点的 `lazy-init="true"`来延迟初始化 bean,这时候,只有第一次获取 bean 会才初始化 bean ~~~ <bean name="user" class="com.spring.User" scope="singleton" lazy-init="true"> <property name="name" value="jelly" /> </bean> ~~~ 如果想对所有 bean 都应用延迟初始化,可以在根节点 beans 设置 `default-lazy-init="true"`,如下: ~~~ <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-lazy-init="true"> ...... </beans> ~~~ # init-method/destory-method 我们希望在 bean 被初始化的时候,就初始化某些资源。为了达到这样的目的,我们可修改代码为: 在类中添加 ~~~ public void init() { System.out.println("我是初始化方法!"); } public void destory() { System.out.println("我是销毁方法!"); } ~~~ 这样,我们的目的就具体地成为:当 Spring 容器初始化对象之后,就要执行该对象的 init() 方法。为了达成这样的目的,只须修改 Spring 的配置文件内容为: ~~~ <bean name="user" class="com.spring.User" scope="singleton" lazy-init="false" init-method="init"> <property name="name" value="jelly" /> </bean> ~~~ 现在我们又希望在 bean 被销毁的时候,就释放或关闭某些资源 ~~~ <bean name="user" class="com.spring.User" scope="singleton" lazy-init="false" destroy-method="destory"> <property name="name" value="jelly" /> </bean> ~~~ 测试方法 ~~~ ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); Object user = ac.getBean("user"); System.out.println(user); //正常关闭spring容器 ac.close(); ~~~ # InitializingBean/DisposableBean 在 spring 容器初始化 bean 和销毁前所做的操作 bean的所有属性都设置完毕后BeanFactory会调用该方法。如果在bean里指定了init-method初始化方法,BeanFactory会先调用afterPropertiesSet然后再调用init-method指定的方法 在单例bean被销毁之前调用destroy()方法。如果在bean里指定了destroy-method销毁方法,BeanFactory会先调用destroy然后再调用destroy-method指定的方法。注意destroy指的是单例,因为当指定指定的生命周期是prototype时,bean由客户端自己管理,容器不在管理bean **注意:destroy-method只对scope=singleton有效果** ~~~ package com.spring; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; public class MyService implements InitializingBean, DisposableBean{ @Override public void afterPropertiesSet() throws Exception { System.out.println("InitializingBean"); } @Override public void destroy() throws Exception { System.out.println("DisposableBean"); } } ~~~ 配置文件 ~~~ <bean id="serviceInit" class="com.spring.MyService"> </bean> ~~~ # 生命周期 * 构造 * postProcessBeforeInitialization * afterPropertiesSet * init ![](https://box.kancloud.cn/7119ae0c6b20435c1d6e9be92c5a4519_907x668.png) 1. instantiate bean对象实例化 2. populate properties 封装属性 3. 如果Bean实现BeanNameAware执行setBeanName 4. 如果Bean实现BeanFactoryAwar或ApplicationContextAwar设置工厂setBeanFactory或上下文对象setApplicationContext 5. 如果存在类实现BeanPostProcessor(后处理Bean),执行postProcessBeforeInitialization 6. 如果Bean实现InitializingBean执行afterPropertiesSet 7. 调用自定义的init-method方法 8. 如果存在类实现BeanPostProcessor(处理Bean),执行postProcessAfterInitialization 9. 执行业务处理 10. 如果Bean实现DisposableBean执行destroy 11. 调用自定义的destroy-method 对于bean的生命周期方法: 第三步与第四步是让Bean了解spring容器。 第五步与第八步 可以针对指定的Bean进行功能增强,这时一般会使用动态代理. 第六步与第十步:通过实现指定的接口来完成init与destroy操作 但是在开发中一般不使用第6步与第10步,原因是我们可以使用第7步与第11步来完成。 第7步与第11步的初始化与销毁操作它无耦合,推荐使用的。但是必须在配置文件中指定初始化与销毁的方法 ~~~ <bean name="user" class="studySpring.User" init-method="init" destroy-method="destory"></bean> ~~~ 然后在User类中写init和destory方法 然后再写测试方法 ~~~ // 1.创建容器对象,因为直接在src下,就写applicationContext.xml ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); // 2.向容器要User对象 Object u = ac.getBean("user"); // 打印User对象 System.out.println(u); // 关闭容器,触发销毁方法,close方法在ClassPathXmlApplicationContext中 ac.close(); ~~~ 总结: 对于bean的生命周期,我们需要关注的主要有两个方法: 1. 增强bean的功能可以使用后处理Bean, BeanPostProcessor 2. 如果需要初始化或销毁操作我们可以使用init-method destroy-method **注意:destroy-method只对scope="singleton"有效果,而且是关闭容器时才触发** # 执行流程 ![](https://box.kancloud.cn/92d36fc67560fbece2f85c048218b04a_172x903.png) Spring 容器中的 Bean 是有生命周期的,Spring 允许在 Bean 在初始化完成后以及 Bean 销毁前执行特定的操作,常用的设定方式有以下三种: 1. 通过实现 InitializingBean/DisposableBean 接口来定制初始化之后/销毁之前的操作方法; 2. 通过 `<bean>` 元素的 init-method/destroy-method属性指定初始化之后 /销毁之前调用的操作方法; 3. 在指定方法上加上@PostConstruct 或@PreDestroy注解来制定该方法是在初始化之后还是销毁之前调用 但他们之前并不等价。即使3个方法都用上了,也有先后顺序. ~~~ Constructor > @PostConstruct >InitializingBean > init-method ~~~