Spring源码-IOC部分-容器初始化过程【2】

时间:2022-09-30 09:24:07
实验环境:spring-framework-5.0.2、jdk8、gradle4.3.1

容器的初始化过程主要通过AbstractApplicationContext的refresh()方法来完成,其主要步骤如下

Spring源码-IOC部分-容器初始化过程【2】

AbstractApplicationContext#refresh()方法

refresh方法
/**
* refresh方法的主要作用是:在创建IoC容器前,如果已经有容器存在,需要把已有的容器销毁和关闭,
* 以保证在refresh方法之后使用的是新创建的IoC容器。
* 它类似于对IoC容器的重启,在新创建的容器中对容器进行初始化,对Bean配置资源进行载入。
*/
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 1、准备刷新,获取当前时间,给容器设置同步表识
prepareRefresh(); // 2、子类刷新并初始化BeanFactory,在这一步生成beanFactory实例(DefaultListableBeanFactory),
// 在这里完成BeanDefinition的加载(loadBeanDefinitions)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 3、初始化beanFactory,设置容器特性,例如类加载器、事件处理器等
prepareBeanFactory(beanFactory); try {
// 4、空方法,bean实例化之前执行。容器子类可以对beanFactory做一些操作
postProcessBeanFactory(beanFactory); // 5、bean实例化之前执行。用户可以继承BeanFactoryPostProcessors接口,在这一步对beanFactory做一些操作
invokeBeanFactoryPostProcessors(beanFactory); // 6、BeanPostProcessors是bean的后置处理器,用于监听容器触发的事件。
// 在bean实例化之后,init-method方法前后执行
// 用户可以继承BeanPostProcessors接口,在这一步对bean方法进行修改,具体执行在step12之后,这一步只是先注册上
registerBeanPostProcessors(beanFactory); // 7、初始化信息源,和国际化相关
initMessageSource(); // 8、初始化事件传播器
initApplicationEventMulticaster(); // 9、空方法,容器子类可以在这一步进行操作
onRefresh(); // 10、为事件传播器,注册事件监听器
registerListeners(); // 11、【重要】实例化所有剩余的非懒加载单例bean,在这一步完成bean的实例化
finishBeanFactoryInitialization(beanFactory); // 12、初始化容器的生命周期事件处理器,并且发布容器的生命周期事件
finishRefresh();
} catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
} // 销毁bean
destroyBeans(); // 取消刷新,重置active标示
cancelRefresh(ex); // Propagate exception to caller.
throw ex;
} finally {
// 清空缓存
resetCommonCaches();
}
}
}

1、prepareRefresh方法

prepareRefresh方法
/**
* 准备刷新上下文,设置启动日期和活动标志、属性源的初始化。
*/
protected void prepareRefresh() {
// 设置启动时间
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true); if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
} // 初始化上下文环境中的任何占位符属性源(空方法,交给子类实现)
initPropertySources(); // 创建并获取环境对象,验证所有标记为必需的属性是否可解析
// 参考 ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties(); // 初始化earlyApplicationEvents,在multicaster可用后发布
this.earlyApplicationEvents = new LinkedHashSet<>();
}

2、obtainFreshBeanFactory方法:在这一步创建了beanFactory实例,并且进行了bean资源的加载

Spring源码-IOC部分-容器初始化过程【2】

obtainFreshBeanFactory方法
/**
* 初始化BeanFactory,在这一步完成了loadBeanDefinitions的加载
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 抽象方法,交给子类实现。
// 子类刷新beanFactory,比如子类AbstractRefreshableApplicationContext会在refreshBeanFactory方法里createBeanFactory,并且执行loadBeanDefinitions加载资源配置。
// 而GenericApplicationContext只会对已经创建好的beanFactory实例设置一下id即可,loadBeanDefinitions放在了外部去做。
refreshBeanFactory(); // getBeanFactory也是抽象方法,由子类创建beanFactory
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}

比如子类AbstractRefreshableApplicationContext对其实现的refreshBeanFactory、getBeanFactory方法如下

refreshBeanFactory方法
/**
* 刷新BeanFactory,实现父类AbstractApplicationContext的抽象方法
*/
@Override
protected final void refreshBeanFactory() throws BeansException {
// 如果已经存在BeanFactory,销毁容器里的bean,关闭BeanFactory
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 创建beanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId()); // 对IOC容器进行定制化,如设置启动参数、开启注解对自动装配等
customizeBeanFactory(beanFactory); // 调用载入bean定义对方法,loadBeanDefinitions(beanFactory)在本类是个抽象方法,交给子类实现
loadBeanDefinitions(beanFactory); // 加锁,写的时候不允许读写
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
} protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
} @Override
public final ConfigurableListableBeanFactory getBeanFactory() {
// 加锁,读的时候不允许写
synchronized (this.beanFactoryMonitor) {
if (this.beanFactory == null) {
throw new IllegalStateException("BeanFactory not initialized or already closed - " +
"call 'refresh' before accessing beans via the ApplicationContext");
}
return this.beanFactory;
}
}

3、prepareBeanFactory方法:对beanFactory做一些初始化的工作,设置一些默认属性

prepareBeanFactory方法
/**
* 为BeanFactory设置一些初始化的属性值,例如上下文的类加载器和后处理器。
*/
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); // Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); // 设置忽略的Aware接口
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); // BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this); // Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); // Detect a LoadTimeWeaver and prepare for weaving, if found.
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
} // Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}

4、postProcessBeanFactory方法

查看代码
/**
* 根据上下文的标准修改其内部bean工厂初始化。所有bean定义都已加载,但没有bean将被实例化。
* 这允许注册特殊的BeanPostProcessors等在某些ApplicationContext实现中。
*/
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
}

比如子类AbstractRefreshableWebApplicationContext对其实现如下

查看代码
/**
* 注册request/session作用域
*/
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 添加Servlet容器相关的后置处理器
beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
beanFactory.ignoreDependencyInterface(ServletConfigAware.class); WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
}

5、invokeBeanFactoryPostProcessors方法:在这一步对BeanDefinition进行增强(相关修改操作)

Spring源码-IOC部分-容器初始化过程【2】

invokeBeanFactoryPostProcessors方法
/**
* BeanFactoryPostProcessor是在spring容器加载了beanDefinition之后,在bean实例化之前执行的。
* 实现BeanFactoryPostProcessor接口,可以在bean实例化之前修改beanDefinition相关配置。
* 可以同时配置多个BeanFactoryPostProcessor,并通过设置'order'属性来控制各个BeanFactoryPostProcessor的执行次序。
*/
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); // 检测LoadTimeWeaver并准备编织(如果同时发现)(例如,通过ConfigurationClassPostProcessor注册的@Bean方法)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}

6、registerBeanPostProcessors方法

查看代码

/**
* BeanPostProcessor,可以在spring容器实例化bean之后,在执行bean的初始化方法前后,添加一些自己的处理逻辑。
*/
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

7、initMessageSource方法

查看代码
/**
* Initialize the MessageSource.
* Use parent's if none defined in this context.
*/
protected void initMessageSource() {
// 这里获取的beanFactory和refresh里obtainFreshBeanFactory获取的是同一个,
ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
// Make MessageSource aware of parent MessageSource.
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
if (hms.getParentMessageSource() == null) {
// Only set parent context as parent MessageSource if no parent MessageSource
// registered already.
hms.setParentMessageSource(getInternalParentMessageSource());
}
}
if (logger.isDebugEnabled()) {
logger.debug("Using MessageSource [" + this.messageSource + "]");
}
}
else {
// Use empty MessageSource to be able to accept getMessage calls.
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME +
"': using default [" + this.messageSource + "]");
}
}
}

8、initApplicationEventMulticaster方法

查看代码
/**
* spring中是通过ApplicationListener及ApplicationEventMulticaster来进行事件驱动开发的,即实现观察者设计模式或发布-订阅模式。
* ApplicationListener监听容器中发布的事件,只要事件发生,就触发监听器的回调,来完成事件驱动开发。属于观察者设计模式中的Observer对象。
* ApplicationEventMulticaster用来通知所有的观察者对象,属于观察者设计模式中的Subject对象。
*/
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory(); // 判断容器中是否存在applicationEventMulticaster
// 也就是自定义的事件监听多路广播器,必须实现ApplicationEventMulticaster接口
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isDebugEnabled()) {
logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
// 如果没有,则默认采用SimpleApplicationEventMulticaster
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
"': using default [" + this.applicationEventMulticaster + "]");
}
}
}

9、onRefresh方法

查看代码
/**
* 模板方法,可以重写该方法以添加特定于上下文的刷新工作。
* 在初始化特殊bean时调用,然后实例化单例。
*/
protected void onRefresh() throws BeansException {
// For subclasses: do nothing by default.
}

10、registerListeners方法

查看代码
/**
* 添加实现ApplicationListener的bean作为监听器。
* 不会影响其他监听器,可以添加这些监听器而无需添加bean。
*/
protected void registerListeners() {
// 首先注册静态指定的监听器
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
} // 不要在这里初始化FactoryBean:我们需要保留所有常规Bean,未初始化以允许后处理器应用于它们!
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
} // 发布早期应用程序事件现在我们终于有了一个multicaster
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}

11、 finishBeanFactoryInitialization 详情见Spring源码-IOC部分-Bean实例化过程【5】

查看代码
/**
* 完成此上下文的bean工厂的初始化,初始化所有剩余的单例bean。
*/
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 1.初始化此上下文的转换服务
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));
} // 2.如果beanFactory之前没有注册嵌入值解析器,则注册默认的嵌入值解析器:主要用于注解属性值的解析。
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
} // 3.初始化LoadTimeWeaverAware Bean实例对象
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class,
false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
} beanFactory.setTempClassLoader(null); // 4.冻结所有bean定义,注册的bean定义不会被修改或进一步后处理,因为马上要创建 Bean 实例对象了
beanFactory.freezeConfiguration(); // 5.实例化所有剩余(非懒加载)单例对象 (这一步很重要,bean的实例化是从这里开始的)
beanFactory.preInstantiateSingletons();
}

12、finishRefresh方法

查看代码
/**
* 完成刷新工作
* 调用LifecycleProcessor的onRefresh方法并发布
*/
protected void finishRefresh() { // 清除上下文级别的资源缓存(例如来自扫描的ASM元数据)。
clearResourceCaches(); // 为此上下文初始化lifecycle processor。
initLifecycleProcessor(); // 首先将刷新传播到lifecycle processor。
getLifecycleProcessor().onRefresh(); // 发布事件
publishEvent(new ContextRefreshedEvent(this)); // 如果active,请参与LiveBeansView MBean。
LiveBeansView.registerApplicationContext(this);
}

参考资料:

《Spring5核心原理与30个类手写》作者 谭勇德

《Spring源码深度解析》作者 郝佳

《Spring技术内幕》作者 计文柯

Spring源码-IOC部分-容器初始化过程【2】的更多相关文章

  1. Spring源码解析 – AnnotationConfigApplicationContext容器创建过程

    Spring在BeanFactory基础上提供了一些列具体容器的实现,其中AnnotationConfigApplicationContext是一个用来管理注解bean的容器,从AnnotationC ...

  2. Spring源码解析-Web容器启动过程

    Web容器启动过程,主要讲解Servlet和Spring容器结合的内容. 流程图如下: Web容器启动的Root Context是有ContextLoaderListener,一般使用spring,都 ...

  3. Spring源码分析之&grave;BeanFactoryPostProcessor&grave;调用过程

    前文传送门: Spring源码分析之预启动流程 Spring源码分析之BeanFactory体系结构 本文内容: AbstractApplicationContext#refresh前部分的一点小内容 ...

  4. Spring源码——IOC控制反转

    1.基础知识 Spring有两个核心功能,分别是ioc和aop,其中ioc是控制反转,aop是切面编程. 在ioc中,还有一个名次叫DI,也就是依赖注入.嗯,好像IOC和DI是指同一个,好像又感觉他俩 ...

  5. Spring 源码学习 04:初始化容器与 DefaultListableBeanFactory

    前言 在前一篇文章:创建 IoC 容器的几种方式中,介绍了四种方式,这里以 AnnotationConfigApplicationContext 为例,跟进代码,看看 IoC 的启动流程. 入口 从 ...

  6. Spring源码系列 — 构造和初始化上下文

    探索spring源码实现,精华的设计模式,各种jdk提供的陌生api,还有那么点黑科技都是一直以来想做的一件事!但是读源码是一件非常痛苦的事情,需要有很大的耐心和扎实的基础. 在曾经读两次失败的基础上 ...

  7. spring源码学习之容器的扩展(二)

    六 BeanFactory的后处理BeanFactory作为spring容器的基础,用于存放所有已经加载的bean,为了保证程序上的高扩展性,spring针对BeanFactory做了大量的扩展,比如 ...

  8. spring源码:web容器启动(li)

    web项目中可以集成spring的ApplicationContext进行bean的管理,这样使用起来bean更加便捷,能够利用到很多spring的特性.我们比较常用的web容器有jetty,tomc ...

  9. spring源码:web容器启动

    web项目中可以集成spring的ApplicationContext进行bean的管理,这样使用起来bean更加便捷,能够利用到很多spring的特性.我们比较常用的web容器有jetty,tomc ...

  10. spring源码-bean之增强初始化-3

    一.ApplicationContext的中文意思是“应用上下文”,它继承自BeanFactory接口,除了包含BeanFactory的所有功能之外,在国际化支持.资源访问(如URL和文件).事件传播 ...

随机推荐

  1. entrar en su zapatilla de deporte en este lugar

    Mientras que yo apareció su campo usando nuestro Nike Glide Wildhorse sólo dos ($ 110) zapatillas de ...

  2. 独立博客怎样申请谷歌Adsense

    谷歌Adsense广告是眼下个人站长的主要赚钱途径之中的一个,首先是它相对诱人的单位价格,尽管谷歌中文广告相比英文广告单位价格有所折扣,但我的经验是仅仅要你的网页内容和广告keyword有较高的匹配性 ...

  3. 玩了一下SDN&colon;MININET&plus;FLOODLIGHT,感觉这确实是一个趋势啊

    功能用增加中间层的方案来解决. 仿佛回到用交换机和路由器模拟器的感觉. 遇到执行命令小问题,狗哥搞定: mininet>mininet> dpctl dump-flows tcp:127. ...

  4. TCP总结

      TCP协议   <计算机网络>谢希仁 及笔记 TCP 的那些事儿(上):http://coolshell.cn/articles/11564.html TCP 的那些事儿(下):htt ...

  5. 【Web】CGI与Servlet技术对比

    CGI:Common Gateway Interface,通用网关接口. 1.CGI处理步骤 首先,客户端(即Web浏览器)根据某资源的URL向Web服务器提出请求:Web服务器的守护进程(HTTP ...

  6. netty源码解解析&lpar;4&period;0&rpar;-3 Channel的抽象实现

    AbstractChannel和AbstractUnsafe抽象类 io.netty.channel.AbstractChannel 从本章开始,会有大量的篇幅涉及到代码分析.为了能够清晰简洁的地说明 ...

  7. Java设计模式—单例模式

    Singleton是一种创建型模式,指某个类采用Singleton模式,则在这个类被创建后,只可能产生一个实例供外部访问,并且提供一个全局的访问点. 核心知识点如下: (1) 将采用单例设计模式的类的 ...

  8. LCA【洛谷P2971】 &lbrack;USACO10HOL&rsqb;牛的政治Cow Politics

    P2971 [USACO10HOL]牛的政治Cow Politics 农夫约翰的奶牛住在N (2 <= N <= 200,000)片不同的草地上,标号为1到N.恰好有N-1条单位长度的双向 ...

  9. any cpu &&num;215&semi;86 &&num;215&semi;64

    On a 32-bit machine: Any CPU: runs as a 32-bit process, can load Any CPU and x86 assemblies, will ge ...

  10. Linux和Windows设备驱动架构比较

    毕业后一直在学操作系统, 有时候觉得什么都懂了,有时候又觉得好像什么都不懂,但总体来说自认为对操作系统实现机制的了解比周围的人还是要多一些.去年曾花了几个星期的晚上时间断断续续翻译了这篇对Linux和 ...