Spring3.1.0实现原理分析(七).填充Bean属性,初始化Bean,登记善后处理,注册单例Bean
大家好,上篇博客我较详细分析了实例化过程,今天继续探讨实例化之后的其它步骤,分别是“填充Bean属性”,“初始化Bean”,“登记善后处理”,“注册单例Bean”,加之实例化,这五个步骤是Spring创建对象的一个完整过程。
一. 填充Bean属性
<bean id="zoo" class="Zoo"><property name="zooName" value="zooName" /><property name="cat" ref="cat" />
</bean><bean id="cat" class="Cat"></bean>
在已获取到对象实例的基础上,这个阶段的任务就是为Bean的属性赋值,比如上图的定义,需要为zoo对象的两个属性“zooName”和“cat”赋值。具体的步骤如下,
1). 首先通过RootBeanDefinition对象的MutablePropertyValues getPropertyValues()方法,获取待赋值给bean属性的属性值集合对象。
2). 然后给予实例化敏感bean后处理器(InstantiationAwareBeanPostProcessor)有机会修改bean实例,调用boolean postProcessAfterInstantiation(Object bean, String beanName)方法对bean实例执行后处理。PS:在Spring启动阶段已经完成了对所有bean后处理的创建和注册,这块内容后续博客会分析。
3). 处理自动装配,前提是用户配置了自动装配策略(BY Name or By Type),默认是禁止自动装配的,并且自动装配也不支持基本类型(诸如Integer、String等)。所谓自动装配就是不需要显式为属性指定值,Spring自动根据属性名称或属性类型,找寻恰当的bean对象为其赋值。经过这个步骤,待赋值给bean属性的属性值变多了。
4). 再次调用实例化敏感bean后处理器,使其有机会在把属性值赋值给bean属性之前,再次执行后处理。这次调用的是后处理器的
PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
方法,从第一个方法参数可以看出,本次后处理主要是针对待赋值给bean属性的属性值的。
5). 对属性值执行解析, 可以参考上篇博客的这段论述。
6). 把属性值赋值给bean对象。
通过Bean包装器实现该能功能,在Spring内部对bean属性的存取都是通过BeanWrapper实现的,具体可以参看这篇博客。 《Spring3.1.0实现原理分析(四).属性访问器(PropertyAccessor)》
BeanWrapper.setPropertyValues(MutablePropertyValues);
二. 初始化Bean
1). 判断bean对象是否实现了Aware相关接口。
a. 如果bean对象实现了BeanNameAware接口,则调用bean对象的setBeanName(String)方法,意味这bean对象可以获取自身的Id。
b. 如果bean对象实现了BeanClassLoaderAware接口,则调用其setBeanClassLoader方法,bean对象可以获取bean工厂的类加载器。
c. 如果bean对象实现了BeanFactoryAware接口,则调用其setBeanFactory(bf)方法,bean对象可以获取bean工厂。
2). 调用所有bean后处理器的如下方法,在初始化之前对bean执行后处理。
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
3). 初始化bean
如果bean实现了InitializingBean接口,则先调用该接口的void afterPropertiesSet() 方法。其次,如果用户配置bean时指定了init-method="..."属性值,则调用该方法对bean执行初始化操作。
4). 再次调用所有bean后处理器的如下方法,在初始化之后对bean执行后处理。
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
三. 登记善后处理 (仅适用于单例bean)
登记善后处理需要同时满足两个条件,分别是:
- bean的生命周期是单例。
- bean实现了可销毁接口(DisposableBean) 或者 配置了销毁方法(destroy-method="...") 或者 容器中存在销毁敏感bean后处理器(DestructionAwareBeanPostProcessor)。
如果以上两个条件满足,那么Spring会为对bean对象创建一个DisposableBeanAdapter对象,这个对象主要持有以下几点信息,
- bean对象是否实现了可销毁接口(DisposableBean) 。
- 如果bean配置了销毁方法(destroy-method="..."),则获取销毁方法名称及方法对象。
- 从当前容器的bean后处理器集合中,过滤出所有销毁敏感bean后处理器(DestructionAwareBeanPostProcessor),作为列表赋值给成员变量。
被创建的DisposableBeanAdapter对象,会被存储到DefaultSingletonBeanRegistry类的成员变量Map<String, Object> disposableBeans中,其中key是bean's Id。当Spring容器被关闭时(即ConfigurableApplicationContext#close()方法被调用),会调用存储在disposableBeans中的所有DisposableBeanAdapter对象的destroy()方法,执行善后处理,具体执行顺序如下,
- 调用销毁敏感bean后处理器的void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;方法。
- 调用DisposableBean接口的destroy()方法。
- 调用用户配置的销毁方法。
补充:对于web应用ConfigurableApplicationContext#close()方法是在ContextLoaderListener监听器中被自动触发的,但是对于桌面应用,如果希望“善后处理”得到执行需要手动调用ConfigurableApplicationContext#registerShutdownHook()方法,当java虚拟机被关闭时,会回调注册的方法。
四. 注册单例Bean(仅适用于单例bean)
- 单例bean对象置入DefaultSingletonBeanRegistry类的成员变量singletonObjects 。
- 把单例bean对象的Id置入DefaultSingletonBeanRegistry类的成员变量registeredSingletons。
/** * 单例对象缓存(key:bean名称;value:单例bean对象) */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>();/*** 已注册的单例bean名称集合*/
private final Set<String> registeredSingletons = new LinkedHashSet<String>(16);
Spring3.1.0实现原理分析(七).填充Bean属性,初始化Bean,登记善后处理,注册单例Bean相关推荐
- Spring3.1.0实现原理分析(七).填充Bean属性,初始化Bean,登记善后处理,注册单例Bean...
大家好,上篇博客我较详细分析了实例化过程,今天继续探讨实例化之后的其它步骤,分别是"填充Bean属性","初始化Bean","登记善后处理" ...
- Spring IOC 容器源码分析 - 创建单例 bean 的过程
1. 简介 在上一篇文章中,我比较详细的分析了获取 bean 的方法,也就是getBean(String)的实现逻辑.对于已实例化好的单例 bean,getBean(String) 方法并不会再一次去 ...
- Spring IOC 容器源码分析 - 获取单例 bean
1. 简介 为了写 Spring IOC 容器源码分析系列的文章,我特地写了一篇 Spring IOC 容器的导读文章.在导读一文中,我介绍了 Spring 的一些特性以及阅读 Spring 源码的一 ...
- Android10.0 ContentProvider原理分析
原文地址:https://skytoby.github.io/2019/ContentProvider%E5%8E%9F%E7%90%86%E5%88%86%E6%9E%90/ 基于Android10 ...
- Android 6.0 JNI原理分析 和 Linux系统调用(syscall)原理
JNI原理 引言:分析Android源码6.0的过程,一定离不开Java与C/C++代码直接的来回跳转,那么就很有必要掌握JNI,这是链接Java层和Native层的桥梁,本文涉及相关源码: fram ...
- Alian解读SpringBoot 2.6.0 源码(七):启动流程分析之准备应用上下文
目录 一.背景 1.1.run方法整体流程 1.2.本文解读范围 二.准备应用上下文 2.1.整体流程 2.2.设置环境 2.3.应用上下文进行后置处理 2.4.应用所有初始化器 2.5.发布应用上下 ...
- Spring IOC核心原理分析
学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的,本文系统分 ...
- Java并发编程学习 + 原理分析(建议收藏)
总结不易,如果对你有帮助,请点赞关注支持一下 微信搜索程序dunk,关注公众号,获取博客源码 Doug Lea是一个无私的人,他深知分享知识和分享苹果是不一样的,苹果会越分越少,而自己的知识并不会因为 ...
- 高通Quick Charge快速充电原理分析
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/zoosenpin/article/details/29799709 1 QC2.0 1.1 高通Qu ...
最新文章
- 【教程】Python数据可视化技巧
- 在线作图|两分钟在线做中性群落模型分析
- Spring4新特性——集成Bean Validation 1.1(JSR-349)到SpringMVC
- Win2008 R2 WEB 服务器设置之禁用不必要的服务和关闭端口
- CentOS最小化系统,怎么安装图形界面
- 基于matlab的霍夫变换,基于matlab的霍夫变换
- OpenCV自动跟踪移动目标DaSiamRPN的实例(附完整代码)
- Nginx中break和last的区别
- parse data from Nacos error
- 计算机设备显示黄色感叹号,电脑没声音,设备管理器中声音出现黄色感叹号怎么办?...
- php 微商城 开源,RF 微商城一款免费开源的基础销售功能的微商城正式发布
- js 弹窗中写html代码,简单了解JavaScript弹窗实现代码
- dw常用标签_DW代码大全
- 服务器虚拟化怎么配置,教你如何配置服务器虚拟化环境
- 海马玩模拟器连接AndroidStudio
- Android call requires API level 12 的解决方案
- 【树莓派】树莓派系统安装
- 成都大数据语言培训:如何提高数据分析能力
- Bonobo Git Server 后台服务安装 详细教程
- 数字图像处理学习笔记之一 DIP绪论与MATLAB基础
热门文章
- 短线看盘比较有效的方法
- 测试老江湖告诉你,测试猿如何优雅的甩锅?
- 优思学院:DMAIC六西格玛改进模型
- Redis基础-下载安装、配置、数据类型、指令、Jedis、持久化
- 线阵相机调帧率_(转)工业相机参数之帧率相关知识详解
- java环形buff_环形缓冲区.ringbuff(C#和java)
- CVE-2017-8464(震网三代)漏洞分析与复现
- 【论文汇总】CVPR2020语义分割医学图像分割paper汇总
- IBM朱辉:大数据分析的5个高复制使用场景及案例分享(含PPT)
- RCS(Real-time control systems) 库