参考:https://blog.csdn.net/w_linux/article/details/80086950

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

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

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

Bean的一生过程

可以简述为以下九步

  1. 实例化bean对象(通过构造方法或者工厂方法)
  2. 设置对象属性(setter等)(依赖注入)
  3. 如果Bean实现了BeanNameAware接口,工厂调用Bean的setBeanName()方法传递Bean的ID。(和下面的一条均属于检查Aware接口)
  4. 如果Bean实现了BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身
  5. 将Bean实例传递给Bean的前置处理器的postProcessBeforeInitialization(Object bean, String beanname)方法
  6. 调用Bean的初始化方法
  7. 将Bean实例传递给Bean的后置处理器的postProcessAfterInitialization(Object bean, String beanname)方法
  8. 使用Bean
  9. 容器关闭之前,调用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()*/@Overridepublic String toString() {return "Student [name = " + name + "]";}//调用BeanNameAware的setBeanName()//传递Bean的ID。@Overridepublic void setBeanName(String name) {System.out.println("调用BeanNameAware的setBeanName()..." ); }}

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>

测试类

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 {@Testpublic void test() {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");Student student = (Student) context.getBean("student");//Bean的使用student.play();System.out.println(student);//关闭容器((AbstractApplicationContext) context).close();}
}

控制台显示结果

可以在输出结果看出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()*/@Overridepublic String toString() {return "Student [name = " + name + "]";}//调用BeanNameAware的setBeanName()//传递Bean的ID。@Overridepublic 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@Overridepublic 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@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanname) throws BeansException {System.out.println("对初始化之前的Bean进行处理,此时我的名字"+bean);return bean;}}

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>

测试类

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 {@Testpublic void test() {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");Student student = (Student) context.getBean("student");//Bean的使用student.play();System.out.println(student);//关闭容器((AbstractApplicationContext) context).close();}
}

控制台显示结果

不添加Bean的后置处理器的控制台输出(前后对比)

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

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

Spring:been的生命周期相关推荐

  1. Spring bean 实现生命周期的三种解决方案

    Spring bean 实现生命周期的三种解决方案 参考文章: (1)Spring bean 实现生命周期的三种解决方案 (2)https://www.cnblogs.com/javawebsoa/a ...

  2. 【Spring】- Bean生命周期

    2019独角兽企业重金招聘Python工程师标准>>> Spring Bean的生命周期: bean对象实例化 属性注入 beanfactory ApplicationContext ...

  3. 字节跳动面试题:“请你描述下 Spring Bean 的生命周期?”

    1. 引言 "请你描述下 Spring Bean 的生命周期?",这是面试官考察 Spring 的常用问题,可见是 Spring 中很重要的知识点. 我之前在准备面试时,去网上搜过 ...

  4. 带你读懂Spring Bean 的生命周期,嘿,就是玩儿~

    带你读懂Spring Bean 的生命周期,嘿,就是玩儿~ 一.前言 今天我们来说一说 Spring Bean 的生命周期,小伙伴们应该在面试中经常遇到,这是正常现象.因为 Spring Bean 的 ...

  5. 请解释Spring Bean 的生命周期?

    Spring Bean 的生命周期简单易懂.在一个bean 实例被初始化时,需要执行一系列的初始化操作以达到可用的状态.同样的,当一个bean 不在被调用时需要进行相关的析构操作,并从bean 容器中 ...

  6. spring生命周期_理解Spring应用上下文生命周期

    Spring应用上下文启动准备阶段 `BeanFactory`创建阶段 `BeanFactory`准备阶段 `BeanFactory`后置处理阶段 `AnnotationConfigServletWe ...

  7. Spring Bean的生命周期及接口回调

    本篇介绍Spring框架为Spring Bean生命周期各阶段提供的回调接口,程序通过实现回调接口,可以在IOC容器实例化或销毁Bean的过程中,得到Bean的控制权,并对Bean进行预处理工作.通过 ...

  8. Spring Bean的生命周期(非常详细)

    Spring作为当前Java最流行.最强大的轻量级框架,受到了程序员的热烈欢迎.准确的了解Spring Bean的生命周期是非常必要的.我们通常使用ApplicationContext作为Spring ...

  9. 再聊Spring Bean的生命周期

    Spring Bean的生命周期是Spring面试热点问题.这个问题即考察对Spring的微观了解,又考察对Spring的宏观认识,想要答好并不容易!本文希望能够从源码角度入手,帮助面试者彻底搞定Sp ...

  10. 【Spring Bean的生命周期】

    Spring Bean的生命周期(非常详细) - Chandler Qian - 博客园

最新文章

  1. 一张照片生成积木的你!5个在校生2个月做的AI项目,李开复看了赞不绝口
  2. 《Spark大数据分析实战》——1.4节弹性分布式数据集
  3. 手机版python3.6.6的requests库下载_Python爬虫之Python3.6 Requests库的基本使用方法
  4. tortoise清理本地分支_本地:延庆运污水环卫抽化粪池
  5. Spring Boot中使用Spring-data-jpa让数据访问更简单、更优雅
  6. thymeleaf There was an unexpected error (type=Internal Server Error, status=500).
  7. python学习2——if 条件检查
  8. Win10 Delete键失效怎么办 ?
  9. Excel多条件计数——COUNTIFS【获奖情况统计】
  10. MySQL 支持表情字符
  11. xposed模块开发第一篇
  12. MacBook Air M1 + MacTex + VS Code的LaTex教程
  13. PCB设计新手入门须知
  14. 【设计原则】里氏代换原则
  15. windows 2003中iis写入事件日志的问题。
  16. 360度全景标定方法_全景摄像机标定方法综述
  17. Json格式字符串转字典
  18. 讯飞语音转文字_录音实时转文字就是如此简单 讯飞智能录音笔SR701评测
  19. mybatis+mysql读取日期2020-09-19返回2020-09-18T16:00:00.000+0000
  20. MySQL数据库的查询:常用查询语句、MySQL函数、多表查询、视图表

热门文章

  1. ESP8266的PC客户端和Arduino两种方式的连接及使用笔记
  2. python 图片生成视频 moviepy_MoviePy
  3. 金字塔打印(C语言)
  4. 内网穿透-公网访问家庭内网
  5. 正则表达式6___常用的正则表达式
  6. 安装第二天import tensorflow 出现如下错误module ‘tensorflow‘ has no attribute ‘compat‘
  7. android 对象存储sd卡,Android网络与数据存储——File存储(实现SD卡文件浏览器)...
  8. 我说百度很垃圾的10条理由
  9. CSS控制字符串换行(汉字好象不行)
  10. SAP字段与表的对应关系