《Spring Boot 源码学习系列》
上篇博文《共享 MetadataReaderFactory 上下文初始化器》,Huazie 带大家详细分析了
SharedMetadataReaderFactoryContextInitializer 。而在 spring-boot-autoconfigure 子模块中预置的上下文初始化器中,除了共享 MetadataReaderFactory 上下文初始化器,还有一个尚未分析。
那么本篇就来详细分析一下 ConditionEvaluationReportLoggingListener 【即 ConditionEvaluationReport 日志记录上下文初始化器】。
在开始本篇的内容介绍之前,我们先来看看往期的系列文章【有需要的朋友,欢迎关注系列专栏】:
Spring Boot 源码学习 |
Spring Boot 项目介绍 |
Spring Boot 核心运行原理介绍 |
【Spring Boot 源码学习】@EnableAutoConfiguration 注解 |
【Spring Boot 源码学习】@SpringBootApplication 注解 |
【Spring Boot 源码学习】走近 AutoConfigurationImportSelector |
【Spring Boot 源码学习】自动装配流程源码解析(上) |
【Spring Boot 源码学习】自动装配流程源码解析(下) |
【Spring Boot 源码学习】深入 FilteringSpringBootCondition |
【Spring Boot 源码学习】OnClassCondition 详解 |
【Spring Boot 源码学习】OnBeanCondition 详解 |
【Spring Boot 源码学习】OnWebApplicationCondition 详解 |
【Spring Boot 源码学习】@Conditional 条件注解 |
【Spring Boot 源码学习】HttpEncodingAutoConfiguration 详解 |
【Spring Boot 源码学习】RedisAutoConfiguration 详解 |
【Spring Boot 源码学习】JedisConnectionConfiguration 详解 |
【Spring Boot 源码学习】初识 SpringApplication |
【Spring Boot 源码学习】Banner 信息打印流程 |
【Spring Boot 源码学习】自定义 Banner 信息打印 |
【Spring Boot 源码学习】BootstrapRegistryInitializer 详解 |
【Spring Boot 源码学习】ApplicationContextInitializer 详解 |
【Spring Boot 源码学习】ApplicationListener 详解 |
【Spring Boot 源码学习】SpringApplication 的定制化介绍 |
【Spring Boot 源码学习】BootstrapRegistry 详解 |
【Spring Boot 源码学习】深入 BootstrapContext 及其默认实现 |
【Spring Boot 源码学习】BootstrapRegistry 初始化器实现 |
【Spring Boot 源码学习】BootstrapContext的实际使用场景 |
【Spring Boot 源码学习】深入 ApplicationContext 初始化器实现 |
【Spring Boot 源码学习】共享 MetadataReaderFactory 上下文初始化器 |
注意: 以下涉及 Spring Boot 源码 均来自版本 2.7.9,其他版本有所出入,可自行查看源码。
我们先来看看 ConditionEvaluationReportLoggingListener 的部分源码,如下:
public class ConditionEvaluationReportLoggingListener implements ApplicationContextInitializer{ private final Log logger = LogFactory.getLog(getClass()); private ConfigurableApplicationContext applicationContext; private ConditionEvaluationReport report; private final LogLevel logLevelForReport; public ConditionEvaluationReportLoggingListener() { this(LogLevel.DEBUG); } public ConditionEvaluationReportLoggingListener(LogLevel logLevelForReport) { Assert.isTrue(isInfoOrDebug(logLevelForReport), "LogLevel must be INFO or DEBUG"); this.logLevelForReport = logLevelForReport; } // 省略。。。 @Override public void initialize(ConfigurableApplicationContext applicationContext) { this.applicationContext = applicationContext; applicationContext.addApplicationListener(new ConditionEvaluationReportListener()); if (applicationContext instanceof GenericApplicationContext) { // Get the report early in case the context fails to load this.report = ConditionEvaluationReport.get(this.applicationContext.getBeanFactory()); } } // 省略。。。 }
从上述源码中,我们可以看出 ConditionEvaluationReportLoggingListener 实现了 ApplicationContextInitializer
它有三个成员变量,分别是:
再来看看构造方法,它有两个:
我们继续查看 initialize 方法,可以看到 :
下面继续来查看 ConditionEvaluationReportListener 的源码:
阅读上述源码,可以看到 ConditionEvaluationReportListener 实现了 GenericApplicationListener 接口,继续翻看 GenericApplicationListener 接口源码:
继续翻看 SmartApplicationListener 接口源码:
从上述源码中,我们发现 GenericApplicationListener 继承了 SmartApplicationListener,而 SmartApplicationListener 则继承了 ApplicationListener。
GenericApplicationListener 是 Spring 框架中的一个接口,它扩展了 ApplicationListener 接口,暴露了更多的元数据,如支持的事件和源类型。在 Spring Framework 4.2 及更高版本中,GenericApplicationListener 替代了基于类的 SmartApplicationListener,允许你使用 ResolvableType 来指定支持的事件类型,而不仅仅是 Class 类型,这样就可以在运行时更准确地解析和匹配事件类型。
知识点: ResolvableType 是 Spring 框架中提供的一个工具类,它用于在运行时解析和处理 Java 泛型信息。在 Java 5 引入泛型之后,为了支持泛型,新增了 Type 类来表示 Java 中的某种类型。然而,反射包中提供的方法在获取泛型类型时,通常返回的是 Type 或其子类的实例,使用时可能需要进行繁琐的强制类型转换。ResolvableType 的出现就是为了简化对泛型信息的获取和处理。它能够将 Class、Field、Method 等描述为 ResolvableType(即转换为 Type),从而方便地进行泛型的解析和操作。通过使用 ResolvableType,你可以轻松地获取 类、接口、属性、方法 等的泛型信息,而无需进行复杂的类型转换或编写繁琐的代码。
现在我们再来看看 ConditionEvaluationReportListener 中重写的 supportsEventType(ResolvableType) 方法:
也就是说,该监听器实际上监听是如下两个事件:
我们继续查看 ConditionEvaluationReportListener 的核心方法 onApplicationEvent ,发现它直接调用了 ConditionEvaluationReportLoggingListener 中的 onApplicationEvent 方法,来实现条件评估报告的日志打印功能。
我们继续查看 ConditionEvaluationReportLoggingListener 中的 onApplicationEvent 方法:
从上图中,可以看到这里针对 3.2 中监听器监听的两个事件分别进行了处理,而这里的核心方法就是 logAutoConfigurationReport(boolean) 方法。
继续查看 logAutoConfigurationReport(boolean) 方法:
从上图中,我们可以简单总结一下:
首先,我们在当前 Spring Boot 项目中设置当前的日志级别为 DEBUG【当然还可以指定其他日志配置文件,这里不展开讲了】:
运行我们的自测类或者应用主类,可以看到如下的运行结果:
从上述运行结果中,可以看出条件评估报告中包含如下的内容:
本篇 Huazie 带大家一起分析了 spring-boot-autoconfigure 子模块中预置的另一个应用上下文初始化器实现 ConditionEvaluationReportLoggingListener ,它实现了条件评估报告的打印记录功能,极大地方便了开发者定位配置类加载问题。
上一篇:nginx漏洞修复