Spring 源码学习 16:单例 Bean 创建
前言在 finishBeanFactoryInitialization 中介绍了创建 Bean 的流程大概流程,这里进入单例 Bean 的创建过程。
这里主要分为三个部分创建单例 Bean
getSingleton
createBean
getObjectForBeanInstance
下面进入源码:
getSingletonpublic Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(beanName, "Bean name must not be null"); // 加锁 synchronized (this.singletonObjects) { // 检查 singletonObjects 缓存中是否有 Object singletonObject = this.singletonObjects.get(beanName); if ...
Spring 源码学习 15:finishBeanFactoryInitialization(重点)
前言可以说前面的都是准备工作,而接下来开始的才是重点,在这一步会完成 BeanFactory 的初始化,同时实例化单例 Bean。
具体怎么操作的,那就一起阅读源码吧!
不过在阅读源码之前,还是需要了解一些知识的。
什么是 FactoryBean ?
FactoryBean 是如何使用的 ?
Bean 是如何初始化的?
常说的循环依赖是怎么解决的?
什么是 FactoryBean ?在官网的这篇文章《What’s a FactoryBean?》中有相关解答,有兴趣的小伙伴可以看一下。
由内部使用的对象实现的接口,这些对象 BeanFactory 本身就是单个对象的工厂。如果 bean 实现此接口,则它将用作对象公开的工厂,而不是直接用作将自身公开的 bean 实例。
注意:实现此接口的 bean 不能用作普通 bean。 FactoryBean以 bean 样式定义,但是为 bean 引用(getObject())公开的对象始终是它创建的对象。
FactoryBeans 可以支持单例和原型,并且可以按需延迟创建对象,也可以在启动时急于创建对象。
当生命一个 FactoryBean ...
Spring 源码学习 14:initApplicationEventMulticaster 、onRefresh 和 registerListeners
前言上一篇介绍了国际化的使用以及初始化消息源的源码,接下来接着往下阅读,将进入 initApplicationEventMulticaster 、onRefresh 和 registerListeners 的相关操作逻辑。
这一部分主要是初始化事件广播器以及注册监听器。而 onRefresh 部分则需要子类去实现。 所以本文主要介绍以下几个部分:
什么是 Spring 事件?
监听器是如何使用的?
什么是 Spring 事件?
这块的介绍在官网 1.15.2. Standard and Custom Events 部分有介绍。
Spring 通过 ApplicationEvent 类和 ApplicationListener 接口提供 ApplicationContext 中的事件处理。如果将实现 ApplicationListener 接口的 bean 部署到上下文中,则每次将 ApplicationEvent 发布到 ApplicationContext 时,都会通知该 bean。本质上,这是标准的观察者设计模式。
归纳下来主要就是三个部分: 事件、事件发布者、事件监听器。 ...
Spring 源码学习 13:initMessageSource
前言在阅读完 registerBeanPostProcessors 源码之后, 下一步就进入到 initMessageSource,这一步主要作用是初始化国际化文件。
依然如之前所示,先通过官网了解到国际化的用法,然后再对源码进行研究。
MessageSource 国际化
如官网1.15.1. Internationalization using MessageSource所示,主要作用就是使用国际化,定制不同的消息。
需要注意的是 MessageSource 定义的 Bean 名字必须为 messageSource, 而如果找不到则会默认注册 DelegatingMessageSource 作为 messageSource 的 Bean。
使用1. 创建国际化文件
2. 声明 MessageSource在 JavaConfig 中 声明 MessageSource , 记得名字一定要叫做 messageSource !
@Configuration@ComponentScan("com.liuzhihang")public class JavaConfig ...
Spring 源码学习 12:registerBeanPostProcessors
前言前面通过 invokeBeanFactoryPostProcessors 这一步了解到了什么是 BeanFactoryPostProcessor ,以及 BeanFactoryPostProcessor 的使用及作用,并通过 invokeBeanFactoryPostProcessors 这一步源码,对 BeanFactoryPostProcessor 的加载流程有了进一步了解。
现在就一起进入下一个环节:
registerBeanPostProcessors(beanFactory);
这一步主要的作用是加载 BeanPostProcessor,从名字也可以看出,只是加载,并没有执行。
不过,在进入源码之前,依然是结合官网,先了解以下几个问题:
什么是 BeanPostProcessor?
BeanPostProcessor 是如何使用的?
BeanPostProcessor 有什么用?
什么是 BeanPostProcessor ?
如截图所示,在官网 1.8.1 Customizing Beans by Using a BeanPostProcessor 中介绍, Bea ...
Spring 源码学习 11:invokeBeanFactoryPostProcessors
前言invokeBeanFactoryPostProcessors 会执行 BeanFactory 的后置处理器。看到这里会有疑问:
什么是 BeanFactoryPostProcessor ?
BeanfactoryPostProcessor 该如何使用?
知道了上面两个问题的答案,对 BeanFactoryPostProcessor 有了了解之后,然后再深入源码,继续阅读 invokeBeanFactoryPostProcessors 这个方法。
作用资料还是在官网可以找到答案:
阅读了一下,大概意思是 Spring IoC 容器允许 BeanFactoryPostProcessor 读取配置元数据,并有可能在容器实例化除 BeanFactoryPostProcessor 实例以外的任何 bean 之前更改它。
同样可以使用 Ordered 接口对 BeanFactoryPostProcessor 进行排序。
注意
BeanFactoryPostProcessor 操作的是 BeanDefinition ,即元数据。但是同样可以通过获取到 BeanFactory 进行实例化 ...
Spring 源码学习 10:prepareBeanFactory 和 postProcessBeanFactory
前言根据 refresh 流程,当 obtainFreshBeanFactory 执行结束后,下一步会执行 prepareBeanFactory ,顾名思义,这个方法主要是准备 BeanFactory,下面一起看一看这部分逻辑。
prepareBeanFactoryprotected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { // Tell the internal bean factory to use the context's class loader etc. // 设置beanFactory的类加载器 beanFactory.setBeanClassLoader(getClassLoader()); // spring.spel.ignore 属性控制是否解析 SpEL 表达式 if (!shouldIgnoreSpel) { beanFactory.setBeanExpressionResolver(new StandardBeanExpres ...
Spring 源码学习 09:refresh 大概流程
前言前面的准备工作结束之后,就是进入核心代码 refresh。
源码public void refresh() throws BeansException, IllegalStateException { // 加锁 synchronized (this.startupShutdownMonitor) { StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh"); // 准备一些上下文 prepareRefresh(); // 获取准备后的 beanFactory DefaultListableBeanFactory ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 准备 BeanFactory prepareBeanFacto ...
Spring 源码学习 08:register 注册配置类
前言看完无参构造的源码及流程之后,后面将会执行 register 方法。
register 方法,入参是我们的配置类 JavaConfig.class ,下面跟着源码继续往下走!
源码分析
this.reader.register(componentClasses);
这里执行的是 reader 的方法,入参就是传入的 JavaConfig.class。
reader 在之前初始化,就是注册一些 PostProcessor。
循环,注册所有的配置类;
doRegisterBean 开始注册。
doRegisterBean 才是真正注册 Bean 的逻辑,从名字也可以有所猜测。下面开始进入 doRegisterBean 的源码阅读:
doRegisterBean
此处代码较长,以截图代替。
通过源码可以看出,这块主要流程:
校验传入的 JavaConfig.class 的注解(是否需要忽略);
处理通用注解;
封装为 BeanDefinitionHolder 后,注册到容器中。
debug
通过 debug 可以看出,在执行完 register 之后,相当于将 JavaC ...
Spring 源码学习 07:ClassPathBeanDefinitionScanner
前言AnnotationConfigApplicationContext 构造函数除了初始化一个 reader ,还有一个 scanner,下面来一起看看 ClassPathBeanDefinitionScanner 都有什么逻辑。
源码分析this.scanner = new ClassPathBeanDefinitionScanner(this); 代码如下所示:
其中 useDefaultFilters 默认设置的 true。所以最终会执行下面三部分代码:
registerDefaultFilters();
setEnvironment(environment);
setResourceLoader(resourceLoader);
再来看下 UML :
ClassPathBeanDefinitionScanner 继承了 ClassPathScanningCandidateComponentProvider,而上面说的这三个方法,其实都是父类 ClassPathScanningCandidateComponentProvider 的方法。
对应的这三个操作就是给它的参 ...