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 ...
随机推荐
- Implementation:UnionFindSet 并查集
class UnionFindSet { private: int *pref; int *rank; int capacity; public: UnionFindSet(int n) { ) { ...
- C# 如何在Linux操作系统下读取文件
发布在Window环境上的微服务需要部署在Linux环境上,本以为没有什么问题,结果因为一处读取文件路径的原因报错了,在此记录一下两个问题:1.C#如何判断当前运行环境是什么操作系统:2.C#读取文件 ...
- react组件里阻事件冒泡
e.nativeEvent.stopImmediatePropagation();
- 热血沙城-3.2移植-古月-cocos2dx源码
最近发现我去年学习2dx的时候移植过的一个游戏现在被放在网上出售 真是有点想笑 本人比较喜欢武侠风格的游戏,当时9秒开源了热血沙城 本着学习的态度 从2.1.2移植到3.2 用了一周的时间 中间各种 ...
- Android 应用安装
DDMS下Files Explorer /data/app/xxx.apk 安装过程:1.拷贝文件xxx.apk到/data/app/xxx-1.apk 2.在/data/data目录下创建一个文件夹 ...
- Django 路由系统URL 视图views
一.Django URL (路由系统) URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL模式以及要为该URL模式调用的视图函数之间的映射表:你就是以这种方式告诉Djan ...
- 304 Not Modified 简述
在客户端向服务端发送http请求时,若返回状态码为304 Not Modified 则表明此次请求为条件请求.在请求头中有两个请求参数:If-Modified-Since 和 If-None-Matc ...
- Oracle EBS AR 收款API收款方法标识无效
1.确认是不是没有收款方法 methods那个表的问题2.查看收款方法那个LOV的问题3.界面录入 是否会有问题 碰到的问题是 收款日期比较早时 找不到对应的收款方法 银行账户需要重新设置
- 第六章 函数、谓词、CASE表达式 6-1 各种各样的函数
一.函数的种类 算术函数 字符串函数 日期函数 转换函数 聚合函数 二.算术函数 + - * / 1.ABS——绝对值 ABS(数值) 绝对值 absolute value ,不考虑数值的符号 ...
- unwrapped与wrapped变量取值的问题
unwrapped与wrapped变量取值的问题 当我们在定义一个tableView时,是可以使用3种定义方式的,第一种就是定义成optional(AnyObject?)形式,第二种为non-opti ...