Spring 了解Bean的一生(生命周期)

Spring 了解Bean的一生(生命周期)该篇博客就来了解 IoC 容器下 Bean 的一生吧 也可以理解为 bean 的生命周期 首先你需要知道的知识在 IoC 容器启动之后 并不会马上就实例化相应的 bean 此时容器仅仅拥有所有对象的 BeanDefiniti BeanDefiniti 是容器依赖某些工具加载的 XML 配置信息进行解析和分析 并将分析后的信息编组为相应的 BeanDefiniti 只有当 getBean 调

该篇博客就来了解IoC容器下Bean的一生吧,也可以理解为bean的生命周期。

首先你需要知道的知识

在IoC容器启动之后,并不会马上就实例化相应的bean,此时容器仅仅拥有所有对象的BeanDefinition(BeanDefinition:是容器依赖某些工具加载的XML配置信息进行解析和分析,并将分析后的信息编组为相应的BeanDefinition)。只有当getBean()调用时才是有可能触发Bean实例化阶段的活动

为什么说有可能触发Bean实例化阶段?

因为当对应某个bean定义的getBean()方法第一次被调用时,不管是显示的还是隐式的,Bean实例化阶段才会被触发,第二次被调用则会直接返回容器缓存的第一次实例化完的对象实例(因为默认是singleton单例,当然,这里的情况prototype类型的bean除外)

该篇博客主要阐述

1、Bean的一生过程
2、Bean的后置处理器

一、Bean的一生过程

先来看以下的图(Bean的一生)

这里写图片描述

可以简述为以下九步

  • 实例化bean对象(通过构造方法或者工厂方法)
  • 设置对象属性(setter等)(依赖注入)
  • 如果Bean实现了BeanNameAware接口,工厂调用Bean的setBeanName()方法传递Bean的ID。(和下面的一条均属于检查Aware接口)
  • 如果Bean实现了BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身
  • 将Bean实例传递给Bean的前置处理器的postProcessBeforeInitialization(Object bean, String beanname)方法
  • 调用Bean的初始化方法
  • 将Bean实例传递给Bean的后置处理器的postProcessAfterInitialization(Object bean, String beanname)方法
  • 使用Bean
  • 容器关闭之前,调用Bean的销毁方法

先看一个最简单的一生(没有使用Bean的后置处理器)

Student.java

package com.linjie.cycle; import org.springframework.beans.factory.BeanNameAware; / * @author LinJie * @Description:一个学生类(Bean),能体现其生命周期的Bean */ public class Student implements BeanNameAware { private String name; //无参构造方法 public Student() { super(); } / 设置对象属性 * @param name the name to set */ public void setName(String name) { System.out.println("设置对象属性setName().."); this.name = name; } //Bean的初始化方法 public void initStudent() { System.out.println("Student这个Bean:初始化"); } //Bean的销毁方法 public void destroyStudent() { System.out.println("Student这个Bean:销毁"); } //Bean的使用 public void play() { System.out.println("Student这个Bean:使用"); } /* 重写toString * @see java.lang.Object#toString() */ @Override public String toString() { return "Student [name = " + name + "]"; } //调用BeanNameAware的setBeanName() //传递Bean的ID。 @Override public void setBeanName(String name) { System.out.println("调用BeanNameAware的setBeanName()..." ); } } 

测试类

package com.linjie.cycle; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; / * 测试类 * @author LinJie * */ public class CycleTest { @Test public void test() { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); Student student = (Student) context.getBean("student"); //Bean的使用 student.play(); System.out.println(student); //关闭容器 ((AbstractApplicationContext) context).close(); } } 

applicationContext.xml

<?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"> <!-- init-method:指定初始化的方法 destroy-method:指定销毁的方法 --> <bean id="student" class="com.linjie.cycle.Student" init-method="initStudent" destroy-method="destroyStudent"> <property name="name" value="LINJIE"></property> </bean> </beans> 

控制台显示结果

这里写图片描述

可以在输出结果看出bean的一生,完全与之前的一生过程图相符(除了bean后置处理器部分),这里还需要提及的是在xml配置中的两个属性

  • init-method:指定初始化的方法
  • destroy-method:指定销毁的方法
说到init-method和destroy-method,当然也要提及一下在< beans>的属性
  • default-init-method:为应用上下文中所有的Bean设置了共同的初始化方法
  • default-destroy-method:为应用上下文中所有的Bean设置了共同的销毁方法

这里写图片描述


二、Bean的后置处理器

上面bean的一生其实已经算是对bean生命周期很完整的解释了,然而bean的后置处理器,是为了对bean的一个增强

用法

分别在Bean的初始化前后对Bean对象提供自己的实例化逻辑

- 实现BeanPostProcessor接口 - postProcessBeforeInitialization方法 - postProcessAfterInitialization方法 

接上面的Student Demo

Student.java

package com.linjie.cycle; import org.springframework.beans.factory.BeanNameAware; / * @author LinJie * @Description:一个学生类(Bean),能体现其生命周期的Bean */ public class Student implements BeanNameAware { private String name; //无参构造方法 public Student() { super(); } / 设置对象属性 * @param name the name to set */ public void setName(String name) { System.out.println("设置对象属性setName().."); this.name = name; } //Bean的初始化方法 public void initStudent() { System.out.println("Student这个Bean:初始化"); } //Bean的销毁方法 public void destroyStudent() { System.out.println("Student这个Bean:销毁"); } //Bean的使用 public void play() { System.out.println("Student这个Bean:使用"); } /* 重写toString * @see java.lang.Object#toString() */ @Override public String toString() { return "Student [name = " + name + "]"; } //调用BeanNameAware的setBeanName() //传递Bean的ID。 @Override public void setBeanName(String name) { System.out.println("调用BeanNameAware的setBeanName()..." ); } } 

MyBeanPostProcessor.java(实现BeanPostProcessor接口)

package com.linjie.cycle; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; / * bean的后置处理器 * 分别在bean的初始化前后对bean对象提供自己的实例化逻辑 * postProcessAfterInitialization:初始化之后对bean进行增强处理 * postProcessBeforeInitialization:初始化之前对bean进行增强处理 * @author LinJie * */ public class MyBeanPostProcessor implements BeanPostProcessor { //对初始化之后的Bean进行处理 //参数:bean:即将初始化的bean //参数:beanname:bean的名称 //返回值:返回给用户的那个bean,可以修改bean也可以返回一个新的bean @Override public Object postProcessAfterInitialization(Object bean, String beanname) throws BeansException { Student stu = null; System.out.println("对初始化之后的Bean进行处理,将Bean的成员变量的值修改了"); if("name".equals(beanname) || bean instanceof Student) { stu = (Student) bean; stu.setName("Jack"); } return stu; } //对初始化之前的Bean进行处理 //参数:bean:即将初始化的bean //参数:beanname:bean的名称 //返回值:返回给用户的那个bean,可以修改bean也可以返回一个新的bean @Override public Object postProcessBeforeInitialization(Object bean, String beanname) throws BeansException { System.out.println("对初始化之前的Bean进行处理,此时我的名字"+bean); return bean; } } 

测试类

package com.linjie.cycle; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; / * 测试类 * @author LinJie * */ public class CycleTest { @Test public void test() { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); Student student = (Student) context.getBean("student"); //Bean的使用 student.play(); System.out.println(student); //关闭容器 ((AbstractApplicationContext) context).close(); } } 

applicationContext.xml

<?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"> <!-- init-method:指定初始化的方法 destroy-method:指定销毁的方法 --> <bean id="student" class="com.linjie.cycle.Student" init-method="initStudent" destroy-method="destroyStudent"> <property name="name" value="LINJIE"></property> </bean> <!-- 配置bean的后置处理器,不需要id,IoC容器自动识别是一个BeanPostProcessor --> <bean class="com.linjie.cycle.MyBeanPostProcessor"></bean> </beans> 

控制台显示结果

这里写图片描述

可以在applicationContext.xml中看到配置Bean后置处理器,不需要ID,只需要其全类名,因为IoC容器自动识别一个BeanPostProcessor

在控制台显示结果可以看出,Bean的后置处理器强大之处,可以对Bean实现自己想要做的事情,比如我这里的Demo就是在postProcessAfterInitialization方法中将成员变量name偷偷修改了,最后输出的就是偷偷修改之后的值

好了以上就是bean的一生,在控制台下将bean的一生映射出来,对理解bean的一生(生命周期)更加直观咯


参考

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/232504.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 安全帽识别算法

    安全帽识别算法应用背景:安全帽作为一种最常见和实用的个人防护用具,能够有效地防止和减轻外来危险源对头部的伤害。但在现场操作过程中,安全帽的佩戴很容易人为忽略,引发了不少人身伤害事故。为了保证工作人员都能在作业中佩戴安全帽,保障作业人员安全,安全帽识别算法系统应运而生。关键字:安全帽识别算法安全帽识别算法技术原理安全帽识别算法采用最新AI人工智能深度学习技术,基于计算机智能视频物体识别算法,且通过规模化的安全帽数据识别训练,赋予监控系统智能识别能力,从而准确判断识别场景内的作业人员是否佩戴安全帽,若检.

    2022年5月12日
    59
  • 蓝桥杯单片机DS18B02温度测量(小数点显示)

    蓝桥杯单片机DS18B02温度测量(小数点显示)

    2021年11月12日
    41
  • 数据结构:表达式求值

    数据结构:表达式求值数据结构:表达式求值表达式求值是程序设计语言编译的一个最基本问题,其中任何一个表达式都是由操作数、运算符(±*/)、界限符(#,(,),[,])组成。运算符和界限符统称算符。算符的优先级关系为(数学角度上):为了通过代码实现,我们定义两个工作栈,一个叫OPTR,存运算符和界限符;另一个存OPND,存操作数或运算结果。首先OPND为空栈,OPTR首先存’#’为栈底元素。依次读取算术表达式…

    2022年6月15日
    32
  • SD卡 MMC卡 MS卡 TF卡

    SD卡 MMC卡 MS卡 TF卡SD卡(SecureDigitalMemoryCard)中文翻译为安全数码卡,是一种基于半导体快闪记忆器的新一代记忆设备。SD卡由日本松下、东芝及美国SanDisk公司于1999年8月共同开发研制。SD卡在24mm×32mm×2.1mm的体积内结合了SanDisk快闪记忆卡控制与MLC(MultilevelCell)技术和Toshiba(东芝)0.16u及0.13u的NAND技术,通过9针…

    2022年5月29日
    81
  • 商城数据库表设计介绍怎么写_商城数据库设计

    商城数据库表设计介绍怎么写_商城数据库设计前言  一个商城系统,需要有,用户表,商品表,商品分类表,购物车表,订单表,订单明细表,支付信息表,以及物流信息表。  使用PowerDesigner对数据表以及他们之间的关系进行了粗略的设计得出了如下E-R图:  1.用户表2.商品表3.商品类别表4.购物车表5.订单表6.订单明细表7.支付信息表8.收货信息表SQL实例SETFOREIGN_KEY_CHECKS=0;———-…

    2025年11月5日
    2
  • 调试HotSpot源代码(配视频)

    调试HotSpot源代码(配视频)

    2020年11月20日
    234

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号