前言

前段时间直接上手使用springboot开发了一个数据平台的后台部分,但是自身对于springboot的原理和过程还不是很清晰,所以反过来学习下springboot的基础。

大家都知道springboot是基于注解的,IOC和AOP是它的两大重要特性,然后AOP又是基于IOC来实现的。那么弄懂IOC就很有必要了。

IOC:控制反转,一种设计思想,它是Spring的核心。简单点说就是spring管理bean的容器。IOC容器一般具备两个基本功能:

  1、通过描述管理Bean,包括发布和获取。

  2、描述Bean之间的依赖关系。这两个问题深究下去是没有边界的,尤其是Bean之间的依赖关系,这个就是spring的核心。

从IOC的概念和功能就引申出了一个重要概念: Bean 

本文将全方位介绍Spring Bean的生命周期

Spring Bean的简要流程:

如上图所示,在XML或者其他文件定义bean之后,spring通过注解的方式将bean传递到IOC容器,IOC容器将bean注册后给类class调用并实例化-构建,之后将bean放入到容器的缓冲池供程序调用。

从图片可以看到Spring Bean 在整个SpringBoot 项目中至关重要,它经过的路径如下:

  1. 实例化  【IOC容器寻找Bean的定义信息并将其实例化】
  2. 设置bean的Aware 【Aware意指能提前感知的,是spring的一个重要接口,使用依赖注入,spring按照Bean定义信息配置Bean的所有属性】
  3. BeanPostProcessor.postProcessBeforeInitialization(Object bean, String beanName)   【如果BeanPostProcessor和Bean关联,那么其postProcessBeforeInitialization()方法将被调用,Spring 框架会遍历得到容器中所有的 BeanPostProcessor ,挨个执行】
  4. InitializingBean.afterPorpertiesSet     【初始化bean, springboot读取properties文件的过程,默认的application.properties 还有其他方式】
  5. BeanPostProcessor.postProcessAfterInitialization(Object bean, String beanName)  【如果有BeanPostProcessor和Bean关联,那么其postProcessAfterInitialization()方法将被调用】
  6. SmartInitializingSingleton.afterSingletonsInstantiated
  7. SmartLifecycle.start
  8. 运行Bean
  9. SmartLifecycle.stop(Runnable callback)     
  10. DisposableBean.destroy()     【销毁】

详细解释

1.实例化对应代码

  【使用合适的初始化方案来创建一个新的bean实例,factory-method,构造器注入或者简单的直接实例化

  实例化策略类:
    InstantiationStrategy

  实例化具体方法:
    AbstractAutowireCapableBeanFactory.createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args)

  

  构造器注入:

    @CompnentScan 【启动类】查找beans,结合@Autowired构造注入【Service层】

  

  Factory Mothod方式也分两种, 分别是静态工厂方法 和 实例工厂方法。

   1. 先创建一个汽车car类 

  1. public class Car {
  2. private int id;
  3. private String name;
  4. private int price;
  5.  
  6. public int getId() {
  7. return id;
  8. }
  9.  
  10. public void setId(int id) {
  11. this.id = id;
  12. }
  13.  
  14. public String getName() {
  15. return name;
  16. }
  17.  
  18. public void setName(String name) {
  19. this.name = name;
  20. }
  21.  
  22. public int getPrice() {
  23. return price;
  24. }
  25.  
  26. public void setPrice(int price) {
  27. this.price = price;
  28. }
  29.  
  30. @Override
  31. public String toString() {
  32. return "Car [id=" + id + ", name=" + name + ", price=" + price + "]";
  33. }
  34.  
  35. public Car(){
  36.  
  37. }
  38.  
  39. public Car(int id, String name, int price) {
  40. super();
  41. this.id = id;
  42. this.name = name;
  43. this.price = price;
  44. }
  45. }

      2. 定义一个工厂类 (定义了1个静态的bean 容器map. 然后提供1个静态方法根据Car 的id 来获取容器里的car对象。)

  1. import java.util.HashMap;
  2. import java.util.Map;
  3.  
  4. public class CarStaticFactory {
  5. private static Map<Integer, Car> map = new HashMap<Integer,Car>();
  6.  
  7. static{
  8. map.put(1, new Car(1,"Honda",300000));
  9. map.put(2, new Car(2,"Audi",440000));
  10. map.put(3, new Car(3,"BMW",540000));
  11. }
  12.  
  13. public static Car getCar(int id){
  14. return map.get(id);
  15. }
  16.  
  17. }

3. 定义配置XML (利用静态工厂方法定义的bean item种, class属性不在是bean的全类名, 而是静态工厂的全类名, 而且还需要指定工厂里的getBean 静态方法名字和参数)

  1. <!--
  2. Static Factory method:
  3. class: the class of Factory
  4. factory-method: method of get Bean Object
  5. constructor-arg: parameters of factory-method
  6. -->
  7. <bean id="bmwCar" class="com.home.factoryMethod.CarStaticFactory" factory-method="getCar">
  8. <constructor-arg value="3"></constructor-arg>
  9. </bean>
  10.  
  11. <bean id="audiCar" class="com.home.factoryMethod.CarStaticFactory" factory-method="getCar">
  12. <constructor-arg value="2"></constructor-arg>
  13. </bean>

     4. 客户端调用factory-method的bean

  1. public static void h(){
  2. ApplicationContext ctx = new ClassPathXmlApplicationContext("bean-factoryMethod.xml");
  3. Car car1 = (Car) ctx.getBean("bmwCar");
  4. System.out.println(car1);
  5.  
  6. car1 = (Car) ctx.getBean("audiCar");
  7. System.out.println(car1);
  8. }

  

2.设置bean的Aware

  【InitializingBean.afterPorpertiesSet,BeanPostProcessor对bean的加工处理基本上在一块出现。】

  设置Aware方法顺序:

  • BeanNameAware
  • BeanClassLoaderAware
  • BeanFactoryAware

  BeanPostProcessor.postProcessBeforeInitialization

  ApplicationContextAwareProcessor也会设置Aware:

  • EnvironmentAware
  • EmbeddedValueResolverAware
  • ResourceLoaderAware
  • ApplicationEventPublisherAware
  • MessageSourceAware
  • ApplicationContextAware

调用afterpropertiesSet方法:位于AbstractAutowireCapableBeanFactory.invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)方法中

源码:

  1. protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
  2.  
  3. // 设置Aware
  4. if (System.getSecurityManager() != null) {
  5. AccessController.doPrivileged(new PrivilegedAction<Object>() {
  6. @Override
  7. public Object run() {
  8. invokeAwareMethods(beanName, bean);
  9. return null;
  10. }
  11. }, getAccessControlContext());
  12. }
  13. else {
  14. invokeAwareMethods(beanName, bean);
  15. }
  16.  
  17. //BeanPostProcessor的postProcessBeforeInitialization
  18. Object wrappedBean = bean;
  19. if (mbd == null || !mbd.isSynthetic()) {
  20. wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
  21. }
  22.  
  23. try {
  24. //调用init方法,其判断是否是InitializingBean的实例,然后调用afterPropertiesSet
  25. invokeInitMethods(beanName, wrappedBean, mbd);
  26. }
  27. catch (Throwable ex) {
  28. throw new BeanCreationException(
  29. (mbd != null ? mbd.getResourceDescription() : null),
  30. beanName, "Invocation of init method failed", ex);
  31. }
  32.  
  33. //BeanPostProcessor的postProcessAfterInitialization
  34. if (mbd == null || !mbd.isSynthetic()) {
  35. wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
  36. }
  37. return wrappedBean;
  38. }

3. SmartInitializingSingleton.afterSingletonsInstantiated的调用位置

  【DefaultListableBeanFactory.preInstantiateSingletons方法,其在所有的bean都实例化完成之后调用】
 
  源码:
  1. @Override
  2. public void preInstantiateSingletons() throws BeansException {
  3. if (this.logger.isDebugEnabled()) {
  4. this.logger.debug("Pre-instantiating singletons in " + this);
  5. }
  6.  
  7. // Iterate over a copy to allow for init methods which in turn register new bean definitions.
  8. // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
  9. List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
  10.  
  11. // Trigger initialization of all non-lazy singleton beans...
  12. // 触发实例化所有的非懒加载的单例
  13. for (String beanName : beanNames) {
  14. ...
  15. }
  16.  
  17. // Trigger post-initialization callback for all applicable beans...
  18. // 触发应用bean的post-initialization回调,也就是afterSingletonsInstantiated方法
  19. for (String beanName : beanNames) {
  20. Object singletonInstance = getSingleton(beanName);
  21. if (singletonInstance instanceof SmartInitializingSingleton) {
  22. final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
  23. if (System.getSecurityManager() != null) {
  24. AccessController.doPrivileged(new PrivilegedAction<Object>() {
  25. @Override
  26. public Object run() {
  27. smartSingleton.afterSingletonsInstantiated();
  28. return null;
  29. }
  30. }, getAccessControlContext());
  31. }
  32. else {
  33. smartSingleton.afterSingletonsInstantiated();
  34. }
  35. }
  36. }
  37. }

4. SmartLifecycle.start

  在ApplicationContext结束刷新finishRefresh时,getLifecycleProcessor().onRefresh();

  判断bean是否为SmartLifecycle并且autoStartup。

  位于:
  DefaultLifecycleProcessor.onRefresh

5. stop方法

  在Application.close的时候,调用getLifecycleProcessor().stop()方法仍然在DefaultLifecycleProcessor内部

6. DisposableBean.destroy方法

  doCreateBean方法中会判断bean是否有销毁相关操作,实现了DisposableBean方法或定义了销毁方法。

  AbstractAutowireCapableBeanFactory.doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)

7. Bean 生命周期演示代码以及运行结果

  1. public class HelloWorld implements SmartInitializingSingleton,SmartLifecycle,InitializingBean,
  2. DisposableBean,MyInterface,BeanNameAware,ApplicationContextAware
  3. {
  4.  
  5. private final Log logger = LogFactory.getLog(getClass());
  6. private boolean isRunning;
  7.  
  8. public HelloWorld() {
  9. System.out.println("实例化");
  10. }
  11.  
  12. public void sayHello(){
  13. System.out.println("hello World");
  14. }
  15.  
  16. public void afterSingletonsInstantiated() {
  17. System.out.println("SmartInitializingSingleton afterSingletonsInstantiated");
  18. }
  19.  
  20. public void start() {
  21. isRunning = true;
  22. System.out.println("LifeCycle start");
  23. }
  24.  
  25. public void stop() {
  26. System.out.println("LifeCycle stop");
  27. }
  28.  
  29. public boolean isRunning() {
  30. return isRunning;
  31. }
  32.  
  33. public boolean isAutoStartup() {
  34. return true;
  35. }
  36.  
  37. public void stop(Runnable callback) {
  38. System.out.println("LifeScycle stop");
  39. callback.run();
  40. }
  41.  
  42. public int getPhase() {
  43. return 0;
  44. }
  45.  
  46. public void afterPropertiesSet() throws Exception {
  47. System.out.println("afterproperties set");
  48. }
  49.  
  50. public void destroy() throws Exception {
  51. System.out.println("destroy");
  52. }
  53.  
  54. public void my(String str) {
  55. System.out.println(str);
  56. }
  57.  
  58. public void setBeanName(String name) {
  59. System.out.println("set bean Name aware");
  60. }
  61.  
  62. public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  63. System.out.println("set Application Aware");
  64. }
  65. }
  66.  
  67. //MyInterface接口
  68. public interface MyInterface {
  69. void my(String str);
  70. }
  71.  
  72. //app.xml
  73. <?xml version="1.0" encoding="UTF-8"?>
  74. <beans xmlns="http://www.springframework.org/schema/beans"
  75. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  76. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  77.  
  78. <bean id="porcessor" class="me.aihe.MyBeanPostProcessor" />
  79. <bean id="hello" class="me.aihe.HelloWorld">
  80.  
  81. </bean>
  82. </beans>
  83.  
  84. //SpringApp
  85. public class SpringApp {
  86. public static void main(String[] args) {
  87. ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("app.xml");
  88. HelloWorld hello = (HelloWorld) applicationContext.getBean("hello");
  89. hello.sayHello();
  90. applicationContext.close();
  91. }
  92. }

总结:

Spring Bean  是整个Spring的基石,意义不言而喻,通过bean可以获取对象,实现容器,反射,简化配置,中间件,线程池等等。所以学习它非常有必要。

【SpringBoot】SpringBoot的基础,全面理解bean的生命周期的更多相关文章

  1. Spring 框架基础(02):Bean的生命周期,作用域,装配总结

    本文源码:GitHub·点这里 || GitEE·点这里 一.装配方式 Bean的概念:Spring框架管理的应用程序中,由Spring容器负责创建,装配,设置属性,进而管理整个生命周期的对象,称为B ...

  2. Spring原理系列一:Spring Bean的生命周期

    一.前言 在日常开发中,spring极大地简化了我们日常的开发工作.spring为我们管理好bean, 我们拿来就用.但是我们不应该只停留在使用层面,深究spring内部的原理,才能在使用时融汇贯通. ...

  3. Spring重点—— IOC 容器中 Bean 的生命周期

    一.理解 Bean 的生命周期,对学习 Spring 的整个运行流程有极大的帮助. 二.在 IOC 容器中,Bean 的生命周期由 Spring IOC 容器进行管理. 三.在没有添加后置处理器的情况 ...

  4. IoC容器装配Bean(xml配置方式)(Bean的生命周期)

    1.Spring管理Bean,实例化Bean对象 三种方式 第一种:使用类构造器实例化(默认无参数) package cn.itcast.spring.initbean; /** * 使用构造方法 实 ...

  5. 深究Spring中Bean的生命周期

    前言 这其实是一道面试题,是我在面试百度的时候被问到的,当时没有答出来(因为自己真的很菜),后来在网上寻找答案,看到也是一头雾水,直到看到了<Spring in action>这本书,书上 ...

  6. spring框架中Bean的生命周期

    一.Bean 的完整生命周期 在传统的Java应用中,bean的生命周期很简单,使用Java关键字 new 进行Bean 的实例化,然后该Bean 就能够使用了.一旦bean不再被使用,则由Java自 ...

  7. 通过BeanPostProcessor理解Spring中Bean的生命周期

    通过BeanPostProcessor理解Spring中Bean的生命周期及AOP原理 Spring源码解析(十一)Spring扩展接口InstantiationAwareBeanPostProces ...

  8. (spring-第1回【IoC基础篇】)Spring容器中Bean的生命周期

    日出日落,春去秋来,花随流水,北雁南飞,世间万物皆有生死轮回.从调用XML中的Bean配置信息,到应用到具体实例中,再到销毁,Bean也有属于它的生命周期. 人类大脑对图像的认知能力永远高于文字,因此 ...

  9. 深入理解Spring中bean的生命周期

    [Spring中bean的生命周期] bean的生命周期 1.以ApplocationContext上下文单例模式装配bean为例,深入探讨bean的生命周期: (1).生命周期图: (2).具体事例 ...

随机推荐

  1. JavaScript高级程序设计(第3版) 第四章(变量、作用域和内存问题)

    4.1 基本类型和引用类型的值             1.基本类型的值是(简单的数据段),引用类型的值是(保存在内存中的对象). 基本类型的值在内存中占据固定大小的空间,因此被保存在栈中.(lifo ...

  2. IOS-swift5.1快速入门之旅

    快速之旅 传统表明,新语言中的第一个程序应在屏幕上打印“Hello,world!”字样.在Swift中,这可以在一行中完成: print("Hello, world!") // P ...

  3. [Codeforces 316E3]Summer Homework(线段树+斐波那契数列)

    [Codeforces 316E3]Summer Homework(线段树+斐波那契数列) 顺便安利一下这个博客,给了我很大启发(https://gaisaiyuno.github.io/) 题面 有 ...

  4. [Codeforces 555E]Case of Computer Network(Tarjan求边-双连通分量+树上差分)

    [Codeforces 555E]Case of Computer Network(Tarjan求边-双连通分量+树上差分) 题面 给出一个无向图,以及q条有向路径.问是否存在一种给边定向的方案,使得 ...

  5. highcharts.js两种数据绑定方式和异步加载数据的使用

    一,我们先来看看异步加载数据的写法(这是使用MVC的例子) 1>js写法 <script src="~/Scripts/jquery-2.1.4.min.js"> ...

  6. 快速部署业务类为webapi服务

    接着前一篇博文,将接口快速打包固定请求格式,不需要修改代码,可以自动完成接口调用,实际上就是生成了一个接口的代理类. 那么仅仅是接口请求代理,没有服务端怎么行?所以需要将实现接口的类部署为webapi ...

  7. 数组Array的方法调用

    <script language="JavaScript" type="text/javascript"> var arr = ["11& ...

  8. js 程序执行与顺序实现详解

    JavaScript是一种描述型脚本语言,由浏览器进行动态的解析与执行,浏览器对于不同的方式有不同的解析顺序,详细介绍如下,感兴趣的朋友可以参考下哈 函数的声明和调用 JavaScript是一种描述型 ...

  9. 270-VC709E 增强版 基于FMC接口的Xilinx Vertex-7 FPGA V7 XC7VX690T PCIeX8 接口卡

    VC709E 增强版 基于FMC接口的Xilinx Vertex-7 FPGA V7 XC7VX690T PCIeX8 接口卡 一.板卡概述       本板卡基于Xilinx公司的FPGA XC7V ...

  10. Error- Overloaded method value createDirectStream in error Spark Streaming打包报错

    直接上代码 StreamingExamples.setStreamingLogLevels() val Array(brokers, topics) = args // Create context ...