ApplicationContext(九)初始化非延迟的 bean

此至,ApplicationContext 已经完成了全部的准备工作,开始初始化剩余的 bean 了(第 11 步)。

public void refresh() throws BeansException, IllegalStateException {
// 11. 初始化剩余的 bean (部分在 invokeBeanFactoryPostProcessors 已经初始化)
finishBeanFactoryInitialization(beanFactory);
}

finishBeanFactoryInitialization 主要是实例化非懒加载的 bean。

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 1. 注册 ConversionService,注意 beanName 必须为 conversionService
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));
} // 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); // 2. 冻结所有的 bean 定义,说明注册的 bean 定义将不被修改
beanFactory.freezeConfiguration(); // 3. 初始化剩下的 bean
beanFactory.preInstantiateSingletons();
}

一、注册 ConversionService

(1) String2DateConverter

public class String2DateConverter implements Converter<String, Date> {
@Override
public Date convert(String source) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
return sdf.parse(source);
} catch (ParseException e) {
;
}
return null;
}
}

(2) 注册

注意:beanName 必须为 conversionService

<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.github.binarylei.spring01.day0728.conversionservice.String2DateConverter"/>
</set>
</property>
</bean>

(3) 测试

@Test
public void test() {
DefaultConversionService service = new DefaultConversionService();
service.addConverter(new String2DateConverter()); Date value = service.convert("2018-08-02", Date.class);
System.out.println(value);
}

二、冻结配置

源代码【DefaultListableBeanFactory】

public void freezeConfiguration() {
this.configurationFrozen = true;
this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames);
}

三、初始化非延迟加载

public void preInstantiateSingletons() throws BeansException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Pre-instantiating singletons in " + this);
} // 1. 创建剩下的单实例 bean
List<String> beanNames = new ArrayList<String>(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)) {
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
@Override
public Boolean run() {
return ((SmartFactoryBean<?>) factory).isEagerInit();
}
}, getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
else {
getBean(beanName);
}
}
} // 2. 筛选出实现了 SmartInitializingSingleton 接口的 bean,回调 afterSingletonsInstantiated() 方法
// @EventListener 注解的方式注册监听器就是在这一步完成的
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
smartSingleton.afterSingletonsInstantiated();
return null;
}
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}

每天用心记录一点点。内容也许不重要,但习惯很重要!

ApplicationContext(九)初始化非延迟的 bean的更多相关文章

  1. spring源码分析系列5:ApplicationContext的初始化与Bean生命周期

    回顾Bean与BeanDefinition的关系. BeanFactory容器. ApplicationContext上下文. 首先总结下: 开发人员定义Bean信息:分为XML形式定义:注解式定义 ...

  2. Spring源码分析(二十四)初始化非延迟加载单例

    摘要: 本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 完成BeanFactory的初始化工作,其中包括ConversionS ...

  3. 7 -- Spring的基本用法 -- 4... 使用 Spring 容器:Spring 容器BeanFactory、ApplicationContext;ApplicationContext 的国际化支持;ApplicationContext 的事件机制;让Bean获取Spring容器;Spring容器中的Bean

    7.4 使用 Spring 容器 Spring 有两个核心接口:BeanFactory 和 ApplicationContext,其中ApplicationContext 是 BeanFactory ...

  4. spring源码分析6: ApplicationContext的初始化与BeanDefinition的搜集入库

    先前几篇都是概念的讲解:回顾下 BeanDefinition 是物料 Bean是成品 BeanFactory是仓库,存储物料与成品 ApplicationContext初始化搜集物料入库,触发生产线, ...

  5. 【转】forbids in-class initialization of non-const static member不能在类内初始化非const static成员

    转自:forbids in-class initialization of non-const static member不能在类内初始化非const static成员 今天写程序,出现一个新错误,好 ...

  6. Error creating bean with name 'mapper' defined in class path resource [applicationcontext.xml]: Cannot resolve reference to bean 'factory' while setting bean property 'sqlSessionFactory'; nested excep

    Error creating bean with name 'mapper' defined in class path resource [applicationcontext.xml]: Cann ...

  7. Spring学习记录(九)---通过工厂方法配置bean

    1. 使用静态工厂方法创建Bean,用到一个工厂类 例子:一个Car类,有brand和price属性. package com.guigu.spring.factory; public class C ...

  8. 关于ApplicationContext的初始化

    一.提倡的初始化方法:<1>在独立应用程序中,获取ApplicationContext:          AbstractApplicationContext context = new ...

  9. Spring MVC 上下文(ApplicationContext)初始化入口

    Spring 常用上下文容器有哪些 ApplicationContext ClassPathXmlApplicationContext ApplicationContext context = new ...

随机推荐

  1. 03_java基础(五)之项目结构搭建

    1.结构图 2.dao代码编辑 package com.day01.station.dao; /** * Created by Administrator on 2018/2/1. */ public ...

  2. package.json bin

    [package.json bin] 1.bin field in your package.json which is a map of command name to local file nam ...

  3. python全栈开发 什么是python python命名及循环

    python全栈 一.  python介绍: 1.    python起源 2.    主要应用领域; web,人工智能,云计算,系统运维. 1.1   python是一门什么语言? python是一 ...

  4. 如何更改Oracle字符集避免乱码

    转一位大神的笔记. 国内最常用的Oracle字符集ZHS16GBK(GBK 16-bit Simplified Chinese)能够支持繁体中文,并且按照2个字符长度存储一个汉字.UTF8字符集是多字 ...

  5. zookeeper报错: org.I0Itec.zkclient.exception.ZkMarshallingError: java.io.EOFException

    zookeeper报错: org.I0Itec.zkclient.exception.ZkMarshallingError: java.io.EOFException 主要因为是没有序列化. 可以使用 ...

  6. dedecms(织梦系统)如何更新手机版首页模板文件

    https://jingyan.baidu.com/article/ad310e80e4b1dd1849f49e8f.html

  7. YouTube Cobalt 浏览器支持

    Cobalt介绍: Cobalt浏览器是YouTube公司定制的一款专用浏览器,Cobalt的使命,是在电视机端,使用灵活多变web形式实现流畅的交互操作,从而替代Android,与普通浏览器不同,C ...

  8. LeetCode第20题

    LeetCode20题不多说上代码 public boolean isValid(String s){ Stack<Character> stack = new Stack<Char ...

  9. HDU-2612.Find way .(不同起点不同终点的BFS)

    我要被这个好用的memset气死了...... 真香 #include <cstring> #include <string> int main () { ]; memset( ...

  10. [剑指Offer]54-二叉搜索树的第k个节点

    题目描述 给定一棵二叉搜索树,找出其中的第k小的结点,返回指向该节点的指针. 思路 中序遍历即可. 注意特判!报段错误数组越界这里就要考虑是少特判的问题. 法一:借助vector 法二(better) ...