该篇博客就来了解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()*/@Overridepublic String toString() {return "Student [name = " + name + "]";}//调用BeanNameAware的setBeanName()//传递Bean的ID。@Overridepublic 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 {@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();}
}

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()*/@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;}}

测试类

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();}
}

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的一生(生命周期)更加直观咯


参考

《Spring揭秘》
《Spring IN ACTION》

Spring 了解Bean的一生(生命周期)相关推荐

  1. 把对象的创建交给spring来管理——  1.创建bean的三种方式     2.bean对象的作用范围     3.bean对象的生命周期

    把对象的创建交给spring来管理 spring对bean的管理细节     1.创建bean的三种方式     2.bean对象的作用范围     3.bean对象的生命周期 创建Bean的三种方式 ...

  2. 一张图搞懂Spring bean的完整生命周期

    转载自 一张图搞懂Spring bean的完整生命周期 一张图搞懂Spring bean的生命周期,从Spring容器启动到容器销毁bean的全过程,包括下面一系列的流程,了解这些流程对我们想在其中任 ...

  3. Spring Bean作用域与生命周期

    目录 Bean的作用域: Bean有六大行为模式 1.singleton:单例模式(默认) 2.prototype: 原型模式(多例模式) 3.request: 请求作用域(Spring MVC) 4 ...

  4. spring工厂生产对象时对象生命周期的三个阶段

    spring生产对象的生命周期包括创建.初始化.销毁. 一.创建 spring创建bean是何时创建的? 如果该bean是单例的,那么和工厂applicationContext的创建一起被创建:如果该 ...

  5. spring源码分析02-spring生命周期源码解析

    spring生命周期流程图: 1.spring扫描 Spring最重要的功能就是帮助程序员创建对象(也就是IOC),而启动Spring就是为创建Bean对象 做准备,所以我们先明白Spring到底是怎 ...

  6. Spring管理的对象的生命周期

    注:完整代码在文章最后 生命周期:就是某个对象从创建到最终销毁整个过程当中会经历的历程! 通常,需要讨论生命周期时,对应的数据类型的对象都不是由开发人员自行维护的! 被容器维护的对象,都是由容器创建对 ...

  7. Bean 作用域和生命周期

    目录 1.作用域定义 Bean 的作用域 Bean 的 6 种作用域 单例作用域(singleton)和全局作用域(application)区别 2.设置作用域 3.Bean 原理分析 3.1 Bea ...

  8. 如何解决Spring Data Maven构建的“生命周期配置未涵盖的插件执行”

    我正在尝试使用Spring Data和Neo4j . 我首先尝试遵循主站点链接的本指南 . 特别是,我的pom.xml基于" Hello,World!". 示例文件 . 这是导致问 ...

  9. 介绍一下Spring Boot启动流程以及生命周期勾子函数?

    代码那些事儿 2020-02-22 16:10:15 上篇文章介绍了Spring Boot自动配置的原理,但是对于Spring Boot应用的整个启动流程还是一头雾水,虽然Spring Boot大大简 ...

最新文章

  1. Oracle数据库入门——常用的数据字典
  2. swift面向对象之属性
  3. java并发临界资源管理
  4. android 原生 电子邮件 应用 发送邮件附带 中文名附件时 附件名称乱码问题解决...
  5. web开发中的跨域问题
  6. java javascript 的编码
  7. linux debain下vim高亮显示
  8. 解读《关于促进大数据发展的行动纲要》
  9. 神经网络中的稀疏编码和自动编码了解一下
  10. 2011英语二长难句
  11. java sqrt函数源码_Java sqrt源码解析
  12. c++ vector容器emplace_back
  13. C语言数据结构-程序设计与算法基础II-电大同步进度
  14. ESP32_esp-adf环境搭建
  15. 苹果审核规则研究,实时更新
  16. 美国国防部发布网络新战略,重点关注中国俄罗斯
  17. VR消防灭火模拟训练系统
  18. 基于Python和TensorFlow的AI作曲的设计与实现
  19. .aspx文件和.aspx.cs文件的区别与联系
  20. 甲方公司必看!如何高效监控外包项目流程?

热门文章

  1. oracle java连接串写法,Oracle可插拔数据库的jdbc连接串写法
  2. 23 种设计模式详解(全23种,含代码样例)
  3. cookie在flask中的应用、flask-login模块的使用(login_user、@login_required、@login_manager.user_loader)current_user
  4. ios调用python_引用ios-和引用ios相关的内容-阿里云开发者社区
  5. JavaScript入门到精通(十三)
  6. go语言实现分布式crontab任务系统
  7. 保存session id的几种方式
  8. Python文本处理:《三国演义》词云的构建与分析
  9. 换发暂住证,迎接奥运会?
  10. 签名算法:SHA1withRSA