写点什么

深入了解 Spring 之上下文

用户头像
邱学喆
关注
发布于: 3 小时前
深入了解Spring之上下文

一. 概述

我们之前介绍Spring Bean 创建过程的 Hookspring 的 IOC 使用以及原理介绍了 BeanFactory 对 Bean 的初始化、属性注入等原理。那么问题来了,由谁来创建 BeanFactory 以及对其的管理呢?答案就是上下文,在 spring 中关键的接口是 ApplicationContext。我们带着问题去了解,ApplicationContext 都做了什么动作,是如何对 BeanFactory 进行管理的?

二. ApplicationContext 关键的实现类

关系图如下:

  • AnnotationConfigServletWebServerApplicationContext 这个 spring-boot 中有关 Servlet 容器中启动类

  • AnnotationConfigWebApplicationContext 这个是 spring-web 支持 Servlet 容器的启动类;

  • AnnotationConfigApplicationContext 这个是原生 spring 常规的启动类;

  • AnnotationConfigReactiveWebApplicationContext 这个是 spring-boot 中基于响应式容器的启动类,主要是 netty 容器;

我们主要讲解 AbstractApplicationContext 抽象类的几大关键属性成员

  • environment 环境对象,保存着系统变量以及配置文件中的变量

  • beanFactoryPostProcessors 保存着对 BeanFactory 前置处理器集合,可以对 BeanFactory 进行管理,如添加 Bean,以及修改 BeanDefinition;

  • resourcePatternResolver 资源解析器,对不同格式的资源进行解析

  • lifecycleProcessor 生命周期处理器,会去调用 BeanFactory 容器有关 Lifecycle 类型的实例,调用它们的 Lifecycle 对应的方法;

  • messageSource 信息资源,主要是面向国际化处理场景

  • applicationEventMulticaster 事件的传播者

  • applicationListeners 监听器集合

  • earlyApplicationEvents 早期上下文启动过程中触发的事件;

三. 关键的逻辑

ApplicationContext 的实现类很多,每个子类实现逻辑都不一样,但它们都要做的动作就是 AbstractApplication 抽象类中的 refresh 方法;注意看数字所备注的关键动作

public void refresh() throws BeansException, IllegalStateException {		synchronized (this.startupShutdownMonitor) {			// 准备上下文刷新前的工作      //1.主要初始化环境对象			prepareRefresh();
// 刷新BeanFactory容器,这个交由子类实现 //2.主要是初始化BeanFactory容器 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//配置BeanFactory容器的特性,如类加载以及前置处理 prepareBeanFactory(beanFactory);
try { //允许BeanFactory初始化后,对其进行修改,如添加BeanPostProcessor等 postProcessBeanFactory(beanFactory);
//调用BeanFactoryPostProcessor对BeanFactory进行修改 //3.调用BeanFactoryPostProcessor对 invokeBeanFactoryPostProcessors(beanFactory);
//初始化BeanPostProcessor并将其注册到BeanFactory中去 registerBeanPostProcessors(beanFactory);
//4.初始化MessageeSource对象 initMessageSource();
//5.初始化事件传播对象 initApplicationEventMulticaster();
// 初始化一些特殊的Bean,交由子类实现 onRefresh();
//6.检测容器中的Listener对象,并保存到上下文中,并将早期触发的事件传播给监听器 registerListeners();
// 7.初始化非懒加载的Bean实例 finishBeanFactoryInitialization(beanFactory);
// 8.完成刷新,主要是做LifecycleProcessor的动作; finishRefresh(); } catch (BeansException ex) { //.... } finally { //... } } }protected void finishRefresh() { // Clear context-level resource caches (such as ASM metadata from scanning). clearResourceCaches();
// Initialize lifecycle processor for this context. initLifecycleProcessor();
// Propagate refresh to lifecycle processor first. getLifecycleProcessor().onRefresh();
// Publish the final event. publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active. LiveBeansView.registerApplicationContext(this); }
复制代码

疑惑:BeanFactoryPostProcessor 实例是什么时候保存到 AbstractApplicationContext 中去的?

在我们创建 ApplicationContext 所对应的子类的实例时,就可以通过该上下文进行添加 BeanFactoryPostProcessor 实例;在 spring-boot 中 servlet 容器的启动类中,调用链如下图:

四. 总结

这里没有过多对过程中的细节进行讲解,只是对其关键的过程粗略的介绍;需要后续针对每个过程进行剖析,

  • Environment 对象,在整个上下文中是如何工作的,以及它的数据结构是怎么样的?

  • BeanFactoryPostProcessor 接口是如何对 BeanFactory 进行配置修改的,它都有哪些实现类,这些实现类都做了什么动作?这里稍微列一下关键的一个实现类 ConfigurationClassPostProcessor 处理器,有关 @Bean、@Configuration、@Import 等等注解都是有这个处理器处理,解析将其注册到 BeanFactory 容器中去;

  • spring 中的事件机制,是如何工作的?在 AbstractApplicationContext 抽象类,保存着 applicationEventMulticaster 事件的传播者和 applicationListeners 监听器集合它们是如何协同工作的。

  • LifecycleProccessor 生命周期处理器是如何工作的,都有哪些类继承了 Lifecycle 类。

用户头像

邱学喆

关注

计算机原理的深度解读,源码分析。 2018.08.26 加入

在IT领域keep Learning。要知其然,也要知其所以然。原理的爱好,源码的阅读。输出我对原理以及源码解读的理解。个人的仓库:https://gitee.com/Michael_Chan

评论

发布
暂无评论
深入了解Spring之上下文