Spring IOC 容器启动、Bean生命周期详解

前言

在Spring IOC 和 AOP 概览中,简要介绍了IOC容器和AOP,没有深入IOC容器Bean的实例化,此文承接上文深入分析Bean的实例化过程、生命周期。

Spring IOC的过程

Spring的IoC容器在实现控制反转和依赖注入的过程中,可以划分为两个阶段:

  1. 容器启动
  2. Bean实例化

容器启动的流程

  1. 容器启动阶段需要扫描 XML/注解/JavaConfig 中需要被Spring管理的Bean信息
  2. 将Bean信息封装成 BeanDefinition 并放入beanDefinitionMap(key:beanName, value:BeanDefinition)中。1、2步骤完成元素据的加载,真实对象还未实例化
  3. 遍历 beanDefinitionMap ,执行 BeanFactoryPostProcessor (Bean工厂后置处理器)来对定义好的 Bean元数据进行获取或修改。
    BeanFactoryPostProcessor 用于Bean实例化前修改Bean的元数据,如修改其中bean定义的某些属性,为bean定义增加其他信息等

完成上述三步后,容器启动完成,开始实例化对象。

Bean实例化过程

在这里插入图片描述

(1)根据 BeanDefinition,利用反射选择合适的构造函数实例化对象。此步只创建对象,但对象属性还没有注入,如:UserService 对象依赖 UserDao,此时 UserService 中的 UserDao 还为null。

(2)注入对象相关属性

(3) 判断 Bean 是否实现了 Aware 相关接口。xxxAware 接口用于获取 xxx资源,如实现 BeanNameAware,则在接口方法能获取到 Bean 的名称。
演示如下(引用自:认识 Aware 接口,此文也介绍了其他一些Aware 接口)

@Component(value = "testBeanName2")
public class MyBeanName implements BeanNameAware {@Overridepublic void setBeanName(String name) {System.out.println("MyBeanName-setBeanName:"+name);}
}

输出:
在这里插入图片描述
(4)调用 BeanPostProcessor 后置处理器的 before 方法。BeanPostProcessor有两个方法,beforeafterBeanPostProcessor是AOP实现的关键。

(5)执行 init 相关方法,如:@PostConstruct标注的方法、实现的InitializingBean接口方法、定义的 init-method 方法

(6)执行BeanPostProcessorafter方法

上述步骤完成了Bean的实例化,Bean会一直保留在上下文容器中,直到容器被销毁。Bean销毁时,会调用配置的 destroy方法。

总结

  1. Spring IOC 分为两个阶段:容器启动和Bean实例化阶段
  2. Spring Bean 的实例化和属性赋值(依赖注入)分两步完成,先实例再注入
  3. Spring Bean的生命周期中有很多的扩展接口:
    Bean实例化前:可以通过 BeanFactoryPostProcessor修改BeanDefinition中Bean的元数据。
    Bean实例化后,初始化时:通过Aware接口,获取资源
    环绕Bean初始化过程BeanPostProcessor的 before 和 after 方法
    初始化阶段:@PostConstruct等 init方法

参考

  • spring-常见知识点(一)
  • 【对线面试官】SpringBean生命周期
  • 006 认识BeanNameAware

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/330064.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java 8 Lambda 表达式(副作用)

【1】转自: https://www.cnblogs.com/linlinismine/p/9283532.html 早在2014年oracle发布了jdk 8,在里面增加了lambda模块。于是java程序员们又多了一种新的编程方式:函数式编程,也就是lambda表达式。我自己用lambda表达式也差不多快4年了&am…

Java NIO:浅析I/O模型

转载自 Java NIO:浅析I/O模型也许很多朋友在学习NIO的时候都会感觉有点吃力,对里面的很多概念都感觉不是那么明朗。在进入Java NIO编程之前,我们今天先来讨论一些比较基础的知识:I/O模型。下面本文先从同步和异步的概念 说起&…

ubuntu安装python3.8_Ubuntu 16.04 安装 python3.8

Ubuntu 16.04 amd64 (64bit)(纯净版) 自带python2.7和python3.5 执行"whereis python"查看当前安装的python [rootroot ~]# whereis python python: /usr/bin/python2.7 /usr/bin/python /usr/lib/python2.7 /usr/lib64/python2.7 /etc/python…

Spring IOC 如何解决循环依赖?

前言 假设对象A、B 之间相互依赖,Spring IOC是如何解决A、B两个对象的实例化的?答案是三级缓存。 三级缓存 SpringIOC 通过三级缓存来解决循环依赖问题,三级缓存指的是三个Map: singletonObjects:一级缓存&#xf…

pythondocx模板_使用python-docx-template修改word文档

由于最近工作中需要自动修改word文档,并生成PDF文件,经过查阅资料后发现使用python-docx-template可以完成对word的修改工作,于是记录一下使用方法。文章内容大部分来自对以下博客的整理和学习https://blog.csdn.net/weixin_42670653/article…

面试必问的 CAS ,要多了解

转载自 面试必问的 CAS ,要多了解前言 CAS(Compare and Swap),即比较并替换,实现并发算法时常用到的一种技术,Doug lea大神在java同步器中大量使用了CAS技术,鬼斧神工的实现了多线程执行的安全性…

MySQL 对于千万级的大表要怎么优化?

很多人第一反应是各种切分; 我给的顺序是: 第一 优化你的sql和索引; 第二 加缓存,memcached,redis; 第三 以上都做了后,还是慢,就做主从复制或主主复制,读写分离,可以在应用层做&…

MySQL元数据库——information_schema

转自: https://www.cnblogs.com/postnull/p/6697077.html 平时使用MySQL客户端操作数据库的同学,只要稍微留神都会发现,除了我们建的库之外,还经常看到三个数据库的影子: 1. information_schema 2. performance_sche…

mysql 表字段信息从一张表迁移到另一张表_MySQL(数据库)笔记

###数据库之前通过流去操作文件保存数据库的弊端:1.执行效率低2.开发成本高3.一般只能保存小量数据4.只能保存文本数据####什么是DB- DataBase 数据库:代表文件集合####什么是DBMS- DataBaseManagementSystem 数据库管理系统(软件),用于管理保存数据的文件集合,用于和程序员进行…

GET与POST传递数据的最大长度能够达到多少

各种web开发语言中,各个页面之间基本都会进行数据的传递,web开发里面比较常用的数据传递方式有get post,一直以来我都只知道get传递的数据量要比post传递的数据量要少,所以传递大数据量还是要用post,但是 get post 这两…

maven命令实战

【1】 创建maven项目 1)目录结构 mavenhello09|---src|---|---main|---|---|---java|---|---|---resources|---|---test|---|---|---java|---|---|---resources|---pom.xml 目录结构说明: main/java:主程序;main/resources&…

Mac 环境变量配置

环境变量配置 cd ~ (回到主目录home)如果你是第一次配置环境变量,可以使用“touch .bash_profile” 创建一个.bash_profile的隐藏配置文件vim .bash_profile,写入相应的环境变量,如下: # golang配置 export GOROOT/usr/local/Ce…

python测试开发面试题_python测试开发面试之深浅拷贝

先来道题热热身 a (a, b,c) c copy.copy(a) d copy.deepcopy(a) if c d: print("c和d的值相等") if id(c) id(d): print("c和d的地址相等") 想想最后打印的是什么? 什么是深拷贝和浅拷贝 深拷贝,就是在对某个对象进行拷贝的时候…

linux虚拟机tomcat上部署web项目的常用命令

1)查看 tomcat是否在运行 ps -ef | grep tomcat ps -ef 补充:Linux中的ps命令是Process Status的缩写,ps命令用来列出系统中当前运行的那些进程。ps命令可以列出当前进程的运行情况(状态、时间等信息)。在Linux系统中…

一文理清Cookie、Session、Token

发展史 1、很久很久以前,Web 基本上就是文档的浏览而已, 既然是浏览,作为服务器, 不需要记录谁在某一段时间里都浏览了什么文档,每次请求都是一个新的HTTP协议, 就是请求加响应, 尤其是我不用记…

python中debug有什么用途_史上最方便的Python Debug工具

最近在github上冒出了一个python的debug神器PySnooper,号称在debug时可以消灭print。那么该工具有哪些优点呢,如何使用该工具呢。本文就介绍该工具的优缺点和使用方式。 前言 使用python开发过程中,总是避免不了debug。传统的debug过程大致分…

能力陷阱总结

【readme】 本文总结于《能力陷阱》,感觉非常不错,有兴趣的朋友可以看下; 【1】领导者的能力陷阱 1)改变思想从行动开始; 改变做事方式,然后才能改变自己的思考方式; 2)要先在行…

Java HashMap 遍历方式性能探讨

转载自 Java HashMap 遍历方式性能探讨关于HashMap的实现这里就不展开了,具体可以参考JDK7与JDK8中HashMap的实现JDK8之前,可以使用keySet或者entrySet来遍历HashMap,JDK8中引入了map.foreach来进行遍历。原因:keySet其实是遍历了…

Raft共识算法

前提条件 Raft不考虑拜庭将军问题,即消息会延迟、丢失但不会错误。 Raft的特性 Strong leader:在 Raft 中,日志条目(log entries)只从 leader 流向其他服务器。 这简化了复制日志的管理,使得 raft 更容易…

直方图 帕累托图_如何发现现象背后的关键因素?帕累托图,质量管理的利器...

大家好:无论在日常生活还是工作中,都会发生一些事情或者结果,是我们不希望发生的。我们也希望从根本上解决掉,但有时候却无从下手,比如本来打算用来看书的时间不知道去哪里了;本来打算存款的钱也不知道去哪…