IOC容器核心流程
Posted 踩踩踩从踩
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了IOC容器核心流程相关的知识,希望对你有一定的参考价值。
前言
本篇文章主要讲解的是spring中ioc容器的核心流程,而Spring IOC容器核心方法在于 Refresh 方法,这个方法里面完成了 Spring 初始化、准备Bean、实例化Bean及扩展功能的实现。因此最重要以及重要的地方就是refresh方法,资源的加载,以及各种扩展功能等等。Refresh方法
ConfigurableApplicationContext#refresh 中进行定义
这个方法用来加载刷新配置,这些配置可能来自, java 配置、 xml 文件、 properties 文件,关系型 数据库,或者其他格式。 作为一个启动方法,它应当在初始化失败后销毁已经创建了的单例,防止占着资源不用。也就是说 调用这个方法,要么没有所有的单例被创建、要么没有没有单例对象创建。经过对该方法的注解解读,发现该方法提供了从加载配置单例bean创建的功能。
这个方法用来加载刷新配置,这些配置可能来自, java 配置、 xml 文件、 properties 文件, 关系型数据库,或者其他格式。 作为一个启动方法,它应当在初始化失败后销毁已经创建了的单例,防止占着资源不用。 也就是说调用这个方法,要么没有所有的单例被创建、要么没有没有单例对象创建。
由AbstractApplicationContext#refresh 实现
public void refresh() throws BeansException, IllegalStateException
synchronized (this.startupShutdownMonitor)
//1 Prepare this context for refreshing.
prepareRefresh();
//2 Tell the subclass to refresh the internal bean factory.
// 为什么要从子类获得刷新后的BeanFactory?
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//3 Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try
//4 Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
//5 Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
//6 Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
//7 Initialize message source for this context.
initMessageSource();
//8 Initialize event multicaster for this context.
initApplicationEventMulticaster();
//9 Initialize other special beans in specific context subclasses.
onRefresh();
//10 Check for listener beans and register them.
registerListeners();
//11 Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
//12 Last step: publish corresponding
event. finishRefresh();
catch (BeansException ex)
if (logger.isWarnEnabled())
logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex);
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller. throw ex;
finally
//13 Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore... resetCommonCaches();
在
AbstractApplicationContext
中的实现,调用了
10
多个方法,来完成该功能。
用来启动和关闭的方法 startupShutdownMonitor 对象。
里面很多方法,都是protected的,因此只能子类进行访问, 例如preparerefresh方法 这些 对于外部是不可知的。
在refresh方法中做的操作
刷新前置的准备 环境属性的添加 然后初始化一些事件监听器列表等等。
整个流程如上图,其中最关键的在于下面的6个方法。
obtainFreshBeanFactory
告诉子类刷新内部的 BeanFactory ,其实就是配置用户属性、加载 Bean 定义,并返回刷新后的 Bean 工厂。prepareBeanFacotry 方法又由两个抽象方法构成,交给子类实现。也就是子类必定含有一个BeanFactory实例,并且还需要提供刷新方法、返回 BeanFactory 实例方法。protected ConfigurableListableBeanFactory obtainFreshBeanFactory()
refreshBeanFactory();
return getBeanFactory();
这里的刷新bean工厂, 一定要重新加载bean定义, bean定义的对象。
对应的实现有AbstractRefreshableApplicationContext、GenericApplicationContext两个类。
AbstractRefreshableApplicationContext
AbstractRefreshableApplicationContext 中实现的刷新方法,可以被多次调用执行。- 自定义Bean工厂属性:Bean定义重写、循环引用等配置
- 创建DefalutListableBeanFactory实例
- 设置ID
- 等待子类实现的,向bean工厂注册Bean定义
- 持有bean工厂实例,以便在getBeanFactory方法中返回出去
GenericApplicationContext
GenericApplicationContext中的刷新方法,只能被调用一次,被Atomic的refreshed状态控制着。
刷新的方法也很简单,只是设置了一个ID。
BeanFactory 在构造函数中创建的。 Bean 定义加载过程都装载了什么。 BeanFactoryPostProcessor 、 BeanPostProcessor、 ApplicationListener 。prepareBeanFacotry
此时, Bean 定义加载完成, Bean 工厂已经被构建了,加下来做的事情就是给 Bean 工厂对象,注入执行后续东西需要的依赖,比如ClassLoader 、 BeanPostProcessor 、环境相关的实例 Bean 。- 给bean工作准备ClassLoader、SPL表达是解析器、属性编辑注册器等
- 向BeanFactory注册ApplicationContextAwareProcessor
- 依赖需要使用的bean,IOC容器自己的多角色身份 @Autowried方式获得下列类型bean
- 注入ApplicationListeners接口实现的发现处理器,同时带有销毁、bean定义混合的实现。
- 操作系统环境变量:JAVA_HOME等
BeanPostProcessor的注入
ApplicationContextAwareProcessor 、 ApplicationListenerDetector 、LoadTimeWeaverAwareProcessor,查看其中一个。 ApplicationContextAwareProcessor 中的实现 只针对EnvironmentAware、EmbeddedValueResolverAware、 ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、 ApplicationContextAware 6种实现进行处理。手动注册环境相关单例 Bean environment 、 systemProperties 、 systemEnvironment
invokeBeanFactoryPostProcessors
bean 工厂基本准备已经完成,但是 Bean 实例还未进行初始化,接下来,调用 BeanFactoryPostProcessor 对 Bean 工厂中的 Bean 定义进行调整。 最重要的处理在委托里面实现 getBeanFactoryPostProcessors()获取的是容器里面的列表属性,这个属性没有机会给外部去 注入BeanFactoryPostProcessor对象。因为ApplicationContext子类在构造函数中调用了refresh方 法。所以这里是个空值。
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors方法解读
BeanFactoryPostProcessor与容器
BeanFactoryPostProcessors的调用处理
PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors 分析 拆分处理: registryProcessors 、 regularPostProcessors 排序处理: PriorityOrdered 、 Ordered 多次调用 BeanFactoryPostProcessors 的分析:在调用 BeanFactoryPostProcessors 过程中,还会 产生 BeanFactoryPostProcessors ,直到所有的 BeanFactoryPostProcessors 处理完毕。registerBeanPostProcessors
此时 Bean 定义加载完成, Bean 工厂完成了刷新实例化,通过了 BeanFactoryProcessor 修整了 Bean 定义,接下来注册BeanPostProcessors 。PostProcessorRegistrationDelegate.registerBeanPostProcessors
注册 BeanPostProcessor 的处理 整体处理逻辑与 BeanFactroyPostProcessor 的处理一样,排序然后调用的处理。 1. priorityOrderedPostProcessors 2. orderedPostProcessors 3. nonOrderedPostProcessors 4. internalPostProcessors 5. ApplicationListenerDetectorinitMessageSource
此时BenPostProcessor都已经注册完成,下一步准备资源国际化的事宜。
如果Bean工厂中存在名为messageSource的bean,则使用它 使用DelegatingMessageSource作为国际化资源处理beanregisterListeners
国际化资源准备完毕,接下来,检查事件监听器,并注册到事件传播器上。在不生成Bean对象的情况下添加ApplicationListener bean作为监听器
这两种去获取 beanfactory的方式。 效果都是一样的。
事件广播器执行方法 SimpleApplicationEventMulticaster#multicastEvent(ApplicationEvent, ResolvableType)
finishBeanFactoryInitialization
完成 bean 工厂的初始化,将 bean 工厂中,非懒加载的单例 bean 进行实例化。finishRefresh
容器的关闭
AbstractApplicationContext#close AbstractApplicationContext#registerShutdownHook AbstractApplicationContext#doClose
以上是关于IOC容器核心流程的主要内容,如果未能解决你的问题,请参考以下文章