SpringBoot运行源码分析:Spring应用上下文创建

愿天堂没有BUG

共 3925字,需浏览 8分钟

 ·

2022-05-10 13:10


忽略信息配置

经过以上步骤,ConfigurableEnvironment 的初 始化和准备工作已经完成。之后,程序又对环境中的忽略信息配置项“spring.beaninfo.ignore”的值进行获取判断,进而设置为系统参数中的忽略项。

private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {
//如果系统参数中 spring. beaninfo. ignore 为 null
if (System. getProperty(
CachedIntrospect ionResults . IGNORE_ BEANINFO_ PROPERTY_ NAME) == null) {
//获取环境中 spring. beaninfo. ignore 的配置
Boolean ignore = environment . getProperty("spring . beaninfo. ignore",
Boolean. class, Boolean.TRUE);
//设置对应的系统参数
System. setProperty( CachedIntrospectionResults . IGNORE_ BEANINFO_ PROPERTY
NAME,
ignore.toString());
}

spring.beaninfo.ignore 的配置用来决定是否跳过 BeanInfo 类的扫描,如果设置为 true,则跳过。


打印 Banner

完成环境的基本处理之后,下面就是控制台 Banner 的打印了。SpringBoot 的 Banner 打印是一个比较酷炫的功能,但又显得有些华而不实,特别是打印图片时启动速度会变慢。这里,我们简单了解一下它的底层代码实现。

Banner 打印是通过 printBanner 方法完成的,相关代码如下。

private Banner printBanner(ConfigurableEnvironment environment) { Q
//如果处于关闭状态,则返回 null
if (this . bannerMode == Banner . Mode .0FF) {
return null;
//如果 resourceL oader 不存在则创建一个默认的 ResourceL oader
ResourceL oader resourcel oader
(this. resourceLoader != null)
? this .resourceLoader : new DefaultResourcel oader(getClassLoader());
//构建 SpringAppl icat ionBannerPrinter
SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBanne
rPrinter(
resourceLoader, this. banner);
//打印到日志中
if (this . bannerMode == Mode.L0G) {
return bannerPr inter . print(environment, this 。mainAppl icationClass, logg
er);
//打印到控制台
return bannerPrinter .print(environment, this .mainApplicationClass, Syste
m. out);
}

上面的代码中展示了 Banner 的开启及打印位置的设置。程序通过 Banner.Mode 枚举值来判 断 是 否 开 启 Banner 打 印 , 此 项 参 数 可 以 在 SpringBoot 入 口 main 方 法 中 通 过setBannerMode 方 法 来 设 置 , 也可 以 通 过 application.properties 中 的spring.main.banner-mode 进行设置。


SpringApplicationBannerPrinter 类承载了 Banner 初始化及打印的核心功能,比如默认如何获取 Banner 信息、如何根据约定优于配置来默认获得 Banner 的内容、Banner 支持的文件格式等。

而 具 体 打 印 的 信 息 是 由 Banner 接 口 的 实 现 类 来 完 成 的 , 比 如 默 认 情 况 下 使 用

SpringBootBanner 来打印 Spring Boot 的版本信息及简单的图形。当然还有通过资源文件打印的 ResourceBanner,通过图片打印的 ImageBanner 等方法。

由于该功能华而不实,就不贴代码占用过多篇幅了,感兴趣的朋友可自行查阅源代码。


Spring应用上下文的创建

在前面的章节中已经多次涉及 WebApplicationType 枚举类,无论是推断 Web 应用类型,还是创建不同的配置环境都与此枚举类有关。Sprina Boot 创建 Spring 的应用上下文时,如果未指定要创建的类,则会根据之前推断出的类型来进行默认上下文类的创建。

在 Spring Boot 中通过 SpringApplication 类中的 createApplicationContext 来进行应用上下文的创建,代码如下。

public static final String DEFAULT_ CONTEXT_ CLASS = "org. springframeworkgon
text."
+ "annotation. Annotat ionConfigApplicationContext";
public static final String DEFAULT_ SERVLET_ WEB_ _CONTEXT_ CLASS = "org.
springf
r amework .
boot."
"web. servlet. context . AnnotationConfigServletWebServerApplicationContex
t"
public static final String DEFAULT REACTIVE_ WEB_ CONTEXT_ CLASS = "org.spring
framework .
+"boot .web.reactive. context .AnnotationConfigReactiveWebServerApplication
Context";
protected ConfigurableApplicat ionContext createApplicationContext() {
/首先获取容器的类变量
Class contextClass = this. applicationContextClass;
//如果为 null,则根据 Web 应用类型按照默认类进行创建
if (contextClass == null) {
try
switch (this .webApplicat ionType)
case
SERVLET:
contextClass
Class. forName (DEFAULT_ SERVLET_ WEB_ CONTEXT_ _CLASS);
break;
ase REACTIVE:
contextClass = Class . forName (DEFAULT_ REACTIVE_ WEB_ _CONTEXT _CLASS);
break;
default:
contextClass = Class. forName(DEFAULT_ _CONTEXT_ _CLASS);
catch (ClassNotFoundException ex) {
/异常处理
//如果存在对应的 Class 配置,则通过 Spring 提供的 BeanUtils 来进行实例化
return (Conf igurableApplicat ionContext) BeanUtils . instantiateClass(contextClass);
}

那么,在 createApplicationContext 方法中,什么时候 applicationContextClass 变量不为null 呢? 比如,当我们 创建 SpringApplication 之后,在调用 run 方法之前,调 用其
setApplicationContextClass 方法指定了 ConfigurableApplicationContext 的设置。但需要注意 的 是 , 该 方 法 不 仅 设 置 了 applicationContextClass 的 值 , 同 时 也 设 置 了webApplicationType 的值,需慎用。

可以看出 createApplicationContext 方法中核心操作就是根据枚举类型进行判断,创建不同的上下文容器,前面已经多次讲到类似的操作,就不再赘述了。


本文给大家讲解的内容是忽略信息配置、打印Banner、Spring应用上下文的创建

  1. 下篇文章给大家讲解的是Spring应用上下文的准备;

  2. 觉得文章不错的朋友可以转发此文关注小编;

  3. 感谢大家的支持!


本文就是愿天堂没有BUG给大家分享的内容,大家有收获的话可以分享下,想学习更多的话可以到微信公众号里找我,我等你哦。

浏览 38
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报