当前位置: 首页 > 图灵资讯 > 技术篇> Bean的生命周期

Bean的生命周期

来源:图灵教育
时间:2023-06-07 09:48:49

1.Bean的生命周期49是什么?

Spring实际上是一家管理Bean对象的工厂。它负责创建对象、销毁对象等。

所谓生命周期,就是对象从创造到最终销毁的整个过程。

Bean对象什么时候创建?

创建Bean对象前后会调用哪些方法?

Bean对象什么时候被销毁?

Bean对象销毁前后调用哪些方法?

2.为什么要知道Bean的生命周期49?

事实上,生命周期的本质是:在哪个时间节点调用哪种方法。

在这条生命线上,我们需要充分了解哪些特殊的时间节点。

只有当我们知道特殊的时间节点在哪里,我们才能确定代码写在哪里。

我们可能需要在特定的时间点执行一个特定的代码,这个代码可以放在这个节点上。当生命线到达这里时,它自然会被调用。

3.Bean生命周期5步49

管理Bean生命周期,可参考Spring的源代码:AbstractautowirecapablebeanFactorydocrebean()方法。

Bean的生命周期大致可以分为五个步骤:

●第一步:实例化Beann

●第二步:Bean属性赋值

●第三步:Bean初始化

●第四步:使用Beann

●第五步:销毁Beann

Bean的生命周期_生命周期

3.1编写测试程序:49

定义一个Bean

package com.powernode.spring6.bean;import org.springframework.beans.BeansException;import org.springframework.beans.factory.*;/** * * 如果Bean的生命周期遵循粗略的五个步骤:  49 * 第一步:实例Bean(调用无参数结构方法。) * 第二步:赋予Bean属性(调用set方法)。) * 第二步:给Bean属性赋值(调用set方法)。 * 第三步:初始化Bean(会调用Bean的init方法。注:这种init方法需要自己写,自己匹配。) * 第四步:使用Beann * 第五步:销毁Bean(会调用Bean的destroy方法。注:这种destroy方法需要自己写,自己配。) **/public class User{    private String name;    public void setName(String name) {        System.out.println(第二步:赋值对象的属性。");        this.name = name;    }    public User() {        System.out.println(一步:实施无参数结构方法。");    }    // 这种方法需要自己写,自己匹配。方法名随意。    public void initBean(){        System.out.println(第三步:初始化Bean。");    }    // 这种方法需要自己写,自己匹配。方法名随意。    public void destroyBean(){        System.out.println(第五步:销毁Bean。");    }//    @Override//    public void setBeanClassLoader(ClassLoader classLoader) {//        System.out.println(Bean这类加载器:" + classLoader);//    }////    @Override//    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {//        System.out.println("生产这个Bean的工厂对象是:" + beanFactory);//    }////    @Override//    public void setBeanName(String name) {//        System.out.println(”这个Bean的名字是:" + name);//    }////    @Override//    public void afterPropertiesSet() throws Exception {//        System.out.println("InitializingBean's afterPropertiesset执行。");//    }////    @Override//    public void destroy() throws Exception {//        System.out.println("DisposableBean's 执行destroy方法”);//    }}

<!-- 研究bean的生命周期 49--> <!--初始化方法和销毁方法需要手动指定。--> <bean id="user" class="com.powernode.spring6.bean.User" init-method="initBean" destroy-method="destroyBean"> <property name="name" value="zhangsan"/> </bean>

////测试bean的生命周期  49    @Test    public void testBeanLifecycleTest(){        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");        User user = applicationContext.getBean("user", User.class);        System.out.println(第四步:使用beann:"+user);        // 注:Spring容器必须手动关闭,这样,Spring容器就会销毁Beann.        ClassPathXmlApplicationContext context = (ClassPathXmlApplicationContext) applicationContext;        context.close();    }

Bean的生命周期_spring_02

3.2应注意:49

●第一:只有正常关闭spring容器,bean的销毁方法才会被调用。

●第二:ClasspathXmlaplicationcontext类有close()方法。

●第三:init-method在配置文件中指定初始化方法。destroy-method指定销毁方法。

3.2.1再次强调

Bean生命周期五步:

第一步:实例化Beann

第二步:Bean属性赋值

第三步:Bean初始化

第四步:使用Beann

第五步:销毁Beann

4.Bean生命周期7步504.1Bean生命周期7步:比五步加的两步在哪里?

在Bean初始化的前后。

第一步:实例化Beann

第二步:Bean属性赋值

第三步:执行“Bean后处理器”的before方法。

第四步:Bean初始化

第五步:执行“Bean后处理器”的after方法。

第六步:使用Beann:

第七步:销毁Beann

在以上五个步骤中,第三步是初始化Bean。如果您想在初始化前后添加代码,可以添加“Bean后处理器”。

编写BeanPostProcessor类,并重写before和after方法:

package com.powernode.spring6.bean;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.BeanPostProcessor;/** * 日志Bean后处理器。  50 **/public class LogBeanPostProcessor implements BeanPostProcessor {    @Override    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {        System.out.println(执行bean后处理器的before方法。");        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);    }    // 该方法有两个参数:    // 第一个参数:刚创建的bean对象。    // 第二个参数:bean的名字。    @Override    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {        System.out.println(”执行Bean后处理器的after方法。");        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);    }}

spring.Bean后处理器配置在xml文件中:

 <!--配备Bean后处理器。  50-->    <!--注:Bean后处理器将作用于整个配置文件中的所有Bean。-->    <bean class="com.powernode.spring6.bean.LogBeanPostProcessor"/>
4.2注意50

一定要注意:在spring.Bean后处理器配置在xml文件中,将作用于当前配置文件中的所有Bean。

如果加上Bean后处理器,Bean的生命周期是7步:

Bean的生命周期_System_04

5.Bean生命周期10步515.1Bean生命周期10步:比七步加的三步在哪里?515.1.1点位1:

在“Bean后处理器”before方法之前

做了什么事?

检查Bean是否实现了与Aware相关的接口,如果实现了接口,则调用这些接口中的方法。

然后调用这些方法的目的是向您传递一些数据,使您更容易使用。

5.1.2点位2:

before方法后的“bean后处理器”

做了什么事?

检查Bean是否实现了InitializingBean接口,如果实现了,则调用接口中的方法。

5.1.3点位3:

使用Bean后,或在销毁Bean之前

做了什么事?

检查Bean是否实现了DisposableBean接口,如果实现了,则调用接口中的方法。

5.1.加入这三个点的特点:

检查Bean是否实现了某些特定的接口,如果实现了这些接口,Spring容器将调用此接口中的方法。

若按源代码跟踪,可分为10步:

Bean的生命周期_spring_05

5.2上图检查Bean是否实现了Aware的相关接口是什么意思?51

与Aware相关的接口包括:BeanNameAware、BeanClassLoaderAware、BeanFactoryAware

●当Bean实现BeanNameAware时,Spring会将Bean的名字传递给Bean。

●当Bean实现BeanClassloaderaware时,Spring将加载Bean的类加载器传递给Bean。

●当Bean实现BeanFactoryAware时,Spring将Bean工厂的对象传递给Bean。

5.3测试上述10个步骤,使User类实现5个接口,并实现所有方法:51

●BeanNameAware

●BeanClassLoaderAware

●BeanFactoryAware

●InitializingBean

●DisposableBean

package com.powernode.spring6.bean;import org.springframework.beans.BeansException;import org.springframework.beans.factory.*;/** * * 如果Bean的生命周期遵循粗略的五个步骤:  49 * 第一步:实例Bean(调用无参数结构方法。) * 第二步:赋予Bean属性(调用set方法)。) * 第三步:初始化Bean(会调用Bean的init方法。注:这种init方法需要自己写,自己匹配。) * 第四步:使用Beann * 第五步:销毁Bean(会调用Bean的destroy方法。注:这种destroy方法需要自己写,自己配。) **/public class User implements        BeanNameAware, BeanClassLoaderAware,BeanFactoryAware,InitializingBean,DisposableBean{    private String name;    public void setName(String name) {        System.out.println(第二步:赋值对象的属性。");        this.name = name;    }    public User() {        System.out.println(一步:实施无参数结构方法。");        this.name = name;    }    public User() {        System.out.println(第一步:实施无参数结构方法。);    }    // 这种方法需要自己写,自己匹配。方法名随意。    public void initBean(){        System.out.println(第四步:初始化Bean。");    }    // 这种方法需要自己写,自己匹配。方法名随意。    public void destroyBean(){        System.out.println(第七步:销毁Bean。");    }    @Override    public void setBeanClassLoader(ClassLoader classLoader) {        System.out.println(Bean这类加载器:" + classLoader);    }    @Override    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {        System.out.println("生产这个Bean的工厂对象是:" + beanFactory);    }    @Override    public void setBeanName(String name) {        System.out.println(”这个Bean的名字是:" + name);    }    @Override    public void afterPropertiesSet() throws Exception {        System.out.println("InitializingBean's afterPropertiesset执行。");    }    @Override    public void destroy() throws Exception {        System.out.println("DisposableBean's 执行destroy方法”);    }}
package com.powernode.spring6.bean;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.BeanPostProcessor;/** * 日志Bean后处理器。  50 **/public class LogBeanPostProcessor implements BeanPostProcessor {    @Override    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {        System.out.println(第三步:执行Bean后处理器的before方法。");        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);    }    // 该方法有两个参数:    // 第一个参数:刚创建的bean对象。    // 第二个参数:bean的名字。    @Override    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {        System.out.println(第五步:执行Bean后处理器的after方法。");        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);    }}
<?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">    <!--配备Bean后处理器。--配备Bean后处理器。  50-->    <!--注:Bean后处理器将作用于整个配置文件中的所有Bean。-->    <bean class="com.powernode.spring6.bean.LogBeanPostProcessor"/><!--    研究bean的生命周期  49-->    <!--初始化方法和销毁方法需要手动指定。-->    <bean id="user" class="com.powernode.spring6.bean.User"          init-method="initBean" destroy-method="destroyBean">        <property name="name" value="zhangsan"/>    </bean><!--    <bean id="vip" class="com.powernode.spring6.bean.Vip"/>--></beans>
package com.powernode.spring6.test;import com.powernode.spring6.bean.User;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class BeanLifecycleTest {    ////测试bean的生命周期  49-50    @Test    public void testBeanLifecycleTest(){        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");        User user = applicationContext.getBean("user", User.class);        System.out.println(第六步:使用bean:"+user);        // 注:Spring容器必须手动关闭,这样,Spring容器就会销毁Beann.        ClassPathXmlApplicationContext context = (ClassPathXmlApplicationContext) applicationContext;        context.close();    }}

Bean的生命周期_生命周期_06

通过测试可以看出:

●InitializingBean的方法早于init-method的执行。

●Disposablebean的方法早于destroy-method的执行。

对于SpringBean的生命周期,掌握之前的7步。够了。

6.Bean有不同的功能域和不同的管理模式

Spring根据Bean的作用域选择管理模式。

●对于singleton作用域的Bean,Spring可以准确地知道Bean何时创建,何时初始化,何时销毁;

●对于prototype作用域的Bean,Spring只负责创建。当容器创建Bean的例子时,Bean的例子将交给客户端代码管理,Spring容器将不再跟踪其生命周期。

让我们把以前的Userspring放在之前.xml文件中的配置scope设置为prototype:

    <!--配备Bean后处理器。  50-->    <!--注:Bean后处理器将作用于整个配置文件中的所有Bean。-->    <bean class="com.powernode.spring6.bean.LogBeanPostProcessor"/><!--    研究bean的生命周期  49-->    <!--初始化方法和销毁方法需要手动指定。-->    <bean id="user" class="com.powernode.spring6.bean.User"          init-method="initBean" destroy-method="destroyBean" scope="prototype">        <property name="name" value="zhangsan"/>    </bean>
/**     * Spring容器只管理singletonBean的完整生命周期。     * 如果是prototype作用域的Bean,Spring容器只负责Bean的初始化。     * 一旦客户端程序获得Bean,Spring容器将不再管理对象的生命周期。     */    ////测试bean的生命周期  49-50    @Test    public void testBeanLifecycleTest(){        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");        User user = applicationContext.getBean("user", User.class);        System.out.println(第六步:使用bean:"+user);        // 注:Spring容器必须手动关闭,这样,Spring容器就会销毁Beann.        ClassPathXmlApplicationContext context = (ClassPathXmlApplicationContext) applicationContext;        context.close();    }

Bean的生命周期_System_07

通过测试一目了然。前8步只执行,第9步和第10步没有执行。

7.如何让Spring管理自己new的对象53?

有时候我们可能会遇到这样的需求。java对象是我们自己的new,然后我们希望Spring容器管理这个对象。如何实现?

package com.powernode.spring6.bean;/** * 如何让Spring管理自己new的对象?  53 **/public class Student {}
////如何让Spring管理自己new的对象?  53    @Test    public void testRegisterBean(){        // 自己new的对象        Student student = new Student();        System.out.println(student);        // 将上述new对象纳入Spring容器进行管理。半路交给Spring进行管理。        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();        factory.registerSingleton("studentBean",student);        // 从spring容器中获取        Object studentBean = factory.getBean("studentBean");        System.out.println(studentBean);    }

Bean的生命周期_spring_08