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

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

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

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

  1. protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
  2. // 1. 注册 ConversionService,注意 beanName 必须为 conversionService
  3. if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
  4. beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
  5. beanFactory.setConversionService(
  6. beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
  7. }
  8. // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
  9. String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
  10. for (String weaverAwareName : weaverAwareNames) {
  11. getBean(weaverAwareName);
  12. }
  13. // Stop using the temporary ClassLoader for type matching.
  14. beanFactory.setTempClassLoader(null);
  15. // 2. 冻结所有的 bean 定义,说明注册的 bean 定义将不被修改
  16. beanFactory.freezeConfiguration();
  17. // 3. 初始化剩下的 bean
  18. beanFactory.preInstantiateSingletons();
  19. }

一、注册 ConversionService

(1) String2DateConverter

  1. public class String2DateConverter implements Converter<String, Date> {
  2. @Override
  3. public Date convert(String source) {
  4. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
  5. try {
  6. return sdf.parse(source);
  7. } catch (ParseException e) {
  8. ;
  9. }
  10. return null;
  11. }
  12. }

(2) 注册

注意:beanName 必须为 conversionService

  1. <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
  2. <property name="converters">
  3. <set>
  4. <bean class="com.github.binarylei.spring01.day0728.conversionservice.String2DateConverter"/>
  5. </set>
  6. </property>
  7. </bean>

(3) 测试

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

二、冻结配置

源代码【DefaultListableBeanFactory】

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

三、初始化非延迟加载

  1. public void preInstantiateSingletons() throws BeansException {
  2. if (this.logger.isDebugEnabled()) {
  3. this.logger.debug("Pre-instantiating singletons in " + this);
  4. }
  5. // 1. 创建剩下的单实例 bean
  6. List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
  7. // Trigger initialization of all non-lazy singleton beans...
  8. for (String beanName : beanNames) {
  9. RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
  10. if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
  11. if (isFactoryBean(beanName)) {
  12. final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
  13. boolean isEagerInit;
  14. if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
  15. isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
  16. @Override
  17. public Boolean run() {
  18. return ((SmartFactoryBean<?>) factory).isEagerInit();
  19. }
  20. }, getAccessControlContext());
  21. }
  22. else {
  23. isEagerInit = (factory instanceof SmartFactoryBean &&
  24. ((SmartFactoryBean<?>) factory).isEagerInit());
  25. }
  26. if (isEagerInit) {
  27. getBean(beanName);
  28. }
  29. }
  30. else {
  31. getBean(beanName);
  32. }
  33. }
  34. }
  35. // 2. 筛选出实现了 SmartInitializingSingleton 接口的 bean,回调 afterSingletonsInstantiated() 方法
  36. // @EventListener 注解的方式注册监听器就是在这一步完成的
  37. for (String beanName : beanNames) {
  38. Object singletonInstance = getSingleton(beanName);
  39. if (singletonInstance instanceof SmartInitializingSingleton) {
  40. final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
  41. if (System.getSecurityManager() != null) {
  42. AccessController.doPrivileged(new PrivilegedAction<Object>() {
  43. @Override
  44. public Object run() {
  45. smartSingleton.afterSingletonsInstantiated();
  46. return null;
  47. }
  48. }, getAccessControlContext());
  49. }
  50. else {
  51. smartSingleton.afterSingletonsInstantiated();
  52. }
  53. }
  54. }
  55. }

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

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. Requests库的文档高级用法

    高级用法 本篇文档涵盖了 Requests 的一些高级特性. 会话对象 会话对象让你能够跨请求保持某些参数.它也会在同一个 Session 实例发出的所有请求之间保持 cookie, 期间使用 url ...

  2. linux启动jmeter(二十三),执行./jmeter.sh报错解决方法(转载)

    转载自 http://www.cnblogs.com/yangxia-test 1.l-bash: ./jmeter.sh: Permission denied解决办法:jmeter.sh的执行权限改 ...

  3. 一、Blender/Python 快速入门

    原文:https://docs.blender.org/api/blender_python_api_current/info_quickstart.html#native-types 1 前言 可以 ...

  4. 调css时候,设置margin-left没有效果

    调css时候,如果设置margin-left没有效果,可能是span不是块元素.设置display:block;即可.

  5. 前端基础之css介绍

    CSS介绍 CSS(Cascading Style Sheet,层叠样式表)定义如何显示HTML元素. 当浏览器读到一个样式表,它就会按照这个样式表来对文档进行格式化(渲染). CSS语法 CSS实例 ...

  6. 织梦 百度sitemap制作教程

    一.新建一个sitemap.htm模板 登录dedecms后台,选择[模板]-[模板管理]-[默认模板管理] 点击最下面的[新建模板]新建一个模板,并复制下面这段代码进去(将代码中的域名改为自己的): ...

  7. CentOS ./configure && make && make install详解

    码的安装一般由3个步骤组成:配置(configure).编译(make).安装(make install). 在Linux中利用源码包安装软件最重要的就是要仔细阅读安装包当中的README  INST ...

  8. shell中参数的传递

    1.命令行参数 向shell脚本传递数据的最基本方式是使用命令行参数. (1) 读取参数 读取输入的参数的变量为位置参数,位置参数通过标准数字表示, 其中$0为程序名称,$1为第一个参数,$2为第二个 ...

  9. .linearDrag on rigidbody / rigidbody2D in code?

    it's rigidbody.drag not .linearDrag 这几天在做一个弹球的游戏,发现小球落下后不会自动停,测试后发现线性阻尼增加后可以 于是加了个触发器不停增加线性阻尼值 priva ...

  10. Delphi: 获取控件文本宽度(像素)

    为适应多语言,需要对界面控件大小.位置多动态改变,因此需要根据其Caption计算实际像素大小. 找资料未有易用现成的,遂参数其它方法,写以函数处之,代码如下: uses TypInfo; funct ...