Spring源码分析(二十四)初始化非延迟加载单例
摘要: 本文结合《Spring源码深度解析》来分析Spring 5.0.6版本的源代码。若有描述错误之处,欢迎指正。
完成BeanFactory的初始化工作,其中包括ConversionService的设置、配置冻结以及非延迟加载的bean的初始化工作。
/**
* Finish the initialization of this context's bean factory,
* initializing all remaining singleton beans.
*/
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
} // Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
} // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
} // Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null); // Allow for caching all bean definition metadata, not expecting further changes.
// 冻结所有的bean定义,说明注册的bean定义将不被修改或任何进一步的处理
beanFactory.freezeConfiguration(); // Instantiate all remaining (non-lazy-init) singletons.
// 初始化剩下的但实例(非惰性的)
beanFactory.preInstantiateSingletons();
}
一、ConversionService的设置
之前我们提到过使用自定义类型转换器从String转换为Date的方式,那么在Spring中还提供了另一种转换方式:使用Converter。同样,我们使用一个简单的示例来了解下Converter的使用方式。
(1)定义转换器。
public class String2DateConverter implements Converter<String, Date> {
@Nullable
@Override
public Date convert(String source) {
try {
return DateUtils.parseDate(source, new String[] {"yyyy-MM-dd HH:mm:ss"});
} catch (ParseException e) {
return null;
}
}
}
(2)注册。
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="org.cellphone.uc.String2DateConverter"/>
</list>
</property>
</bean>
(3)测试。
public class UserManager {
private Date dateValue;
public Date getDateValue() {
return dateValue;
}
public void setDateValue(Date dateValue) {
this.dateValue = dateValue;
}
@Override
public String toString() {
return "dataValue: " + dateValue;
}
}
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring/beans-test.xml");
UserManager manager = (UserManager) context.getBean("userManager");
System.out.println(manager);
}
通过以上的功能我们看到了Converter以及ConversionService提供的便利功能,其中的配置就是在当前函数中被初始化的。
二、冻结配置
冻结所有的bean定义,说明注册的bean定义将不被修改或进行任何进一步的处理。
@Override
public void freezeConfiguration() {
this.configurationFrozen = true;
this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames);
}
三、初始化非延迟加载
ApplicationContext实现的默认行为就是在启动时将所有单例bean提前进行实例化。提前实例化意味者作为初始化过程的一部分,ApplicationContext实例会创建并配置所有的单例bean。通常情况下这是一件好事,因为这样在配置中的任何错误就会即刻被发现(否则的话可能要花几个小时甚至几天)。而这个实例的过程就是在finishBeanFactoryInitialization中完成的。
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isDebugEnabled()) {
logger.debug("Pre-instantiating singletons in " + this);
} // Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames); // Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
getBean(beanName);
}
}
} // Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
Spring源码分析(二十四)初始化非延迟加载单例的更多相关文章
- Spring源码分析(十四)从bean的实例中获取对象
摘要:本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 在getBean方法中,getObjectForBeanlnstance ...
- Vue.js 源码分析(二十四) 高级应用 自定义指令详解
除了核心功能默认内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令. 官网介绍的比较抽象,显得很高大上,我个人对自定义指令的理解是:当自定义指令作用在一些DOM元素或组件上 ...
- ABP源码分析二十四:Notification
NotificationDefinition: 用于封装Notification Definnition 的信息.注意和Notification 的区别,如果把Notification看成是具体的消息 ...
- Spring源码分析(十三)缓存中获取单例bean
摘要:本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 介绍过FactoryBean的用法后,我们就可以了解bean加载的过程了 ...
- 【spring源码分析】IOC容器初始化(二)
前言:在[spring源码分析]IOC容器初始化(一)文末中已经提出loadBeanDefinitions(DefaultListableBeanFactory)的重要性,本文将以此为切入点继续分析. ...
- 【spring源码分析】IOC容器初始化(四)
前言:在[spring源码分析]IOC容器初始化(三)中已经分析了BeanDefinition注册之前的一些准备工作,下面将进入BeanDefinition注册的核心流程. //DefaultBean ...
- 【spring源码分析】IOC容器初始化(十)
前言:前文[spring源码分析]IOC容器初始化(九)中分析了AbstractAutowireCapableBeanFactory#createBeanInstance方法中通过工厂方法创建bean ...
- 【spring源码分析】IOC容器初始化——查漏补缺(二)
前言:在[spring源码分析]IOC容器初始化(八)中多次提到了前置处理与后置处理,本篇文章针对此问题进行分析.Spring对前置处理或后置处理主要通过BeanPostProcessor进行实现. ...
- 【spring源码分析】IOC容器初始化(总结)
前言:在经过前面十二篇文章的分析,对bean的加载流程大致梳理清楚了.因为内容过多,因此需要进行一个小总结. 经过前面十二篇文章的漫长分析,终于将xml配置文件中的bean,转换成我们实际所需要的真正 ...
- Spring源码分析(十八)创建bean
本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 目录 一.创建bean的实例 1. autowireConstructor 2 ...
随机推荐
- JavaScript中如何将html字符串转化为Jquery对象或者Dom对象
最近在开发百度地图相关的一个应用,需要从硬编码的html字符串中提取自己想要的元素以及属性信息.但是在js中或者jQuery中操作元素节点以及属性都是使用DOM对象或者jquery对象.下面将介绍如何 ...
- js判断移动端页面按home键切换到桌面事件
---恢复内容开始--- 原理就是通过页面标签切换事件(visibilitychange)来判断,亦可用户移动端桌面和app切换. 先看代码: var hiddenProperty = 'hidden ...
- Ubuntu加入opencv库的环境变量
1.用gedit打开/etc/ld.so.conf 终端输入: sudo gedit /etc/ld.so.conf 文件末行加入:include /usr/loacal/lib .然后终端执行指令: ...
- CentOS7系列--1.5CentOS7配置vim
CentOS7配置vim 1. 安装vim [root@centos7 ~]# yum -y install vim-enhanced Loaded plugins: fastestmirror ba ...
- 漂亮的ActionBar效果
Newsstand—这个应用引进了新的方式,使得ActionBar达到了新的水平.如果你打开这个应用的发布页,你会注意到不带图标的ActionBar是半透明的,而且和一个大的图片集(一个大的杂志图标, ...
- 一:JavaWeb和Tomcat的安装
1.Java Web 是java技术用来解决相关web互联网领域的技术总和. 2.Servlet是Java Servlet的简称,称为小服务程序或服务器连接器,用Java编写的服务器端程序 3.JSP ...
- zookeeper应用 - FIFO 队列 分布式队列
使用ZooKeeper实现的FIFO队列,这个队列是分布式的. package fifo; import java.util.Collections; import java.util.List; i ...
- 《Think in JAVA》之每日一读(initianlize)——2013/11/12、13
了解包括继承在内的初始化全过程,以对所发生的的一切有一个全局的把握,是很有益的. 请看下例: package initialize; class Insect { private int i = 9; ...
- Linux man 命令详细介绍
知道linux帮助文件(man-pages,手册页)一般放在,$MANPATH/man 目录下面,而且按照领域与语言放到不同的目录里面. 看了上一章,要找那个命令使用相关手册,只要我们按照领域区分,到 ...
- [控件] 心形加载的view
心形加载的view 效果: 素材图片: 源码: StarView.h 与 StarView.m // // StarView.h // Star // // Created by XianMingYo ...