1.Spring Boot源码解析(四)ApplicationContext准备阶段
2.BeanWrapper
Spring Boot源码解析(四)ApplicationContext准备阶段
深入解析Spring Boot中ApplicationContext的准备阶段,本文将带你从环境设置、后处理到初始化器的执行,直至广播事件和注册应用参数等关键步骤的全面解读。
环境的设置是准备阶段的起点,主要涉及三个步骤。javaweb出题系统源码首先,通过AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner,将包含实际参数的Environment重新配置到这些实例中,以确保ApplicationContext能够准确理解和处理后续的配置信息。
紧接着,对ApplicationContext进行后处理。这包括注册beanNameGenerator、设置resourceLoader和conversionService。对于一般配置的Spring Boot应用,这些部分往往为空,仿源码网站源码下载因此主要执行的是设置conversionService,确保数据转换的顺利进行。
处理Initializer阶段,Spring Boot通过遍历META-INF/spring.factories中的initializer加载配置,执行8个预设的Initializer方法,它们负责执行特定的功能,例如增强或定制ApplicationContext行为,尽管具体实现细节未详细展开。
广播ApplicationContextInitialized和BootstrapContextClosed事件,以及注册applicationArguments和printedBanner,是准备阶段的后续操作,确保ApplicationContext能够接收外部参数并展示启动信息,同时为ApplicationContext的后续操作做准备。
在设置不支持循环引用和覆盖后,调整lazy initialization为默认不允许。android源码读源码方法Spring Boot通过配置确保依赖注入过程的高效性和稳定性,同时提供了开启懒加载的选项,允许在实际使用时加载bean,提高应用启动性能。
最后,处理重排属性的post processor,确保ConfigurationClassPostProcessor加载的property在正确的位置被处理,维护配置加载的逻辑顺序和依赖关系。
资源的加载是准备阶段的最后一步,将PrimarySource与所有其他源整合到allSources中,并返回一个不可修改的集合。这个过程确保了资源的高效访问和管理,为ApplicationContext的后续操作提供基础。
在完成启动类的加载后,Spring Boot通过构建BeanDefinitionLoader并配置相应的源码天空咋下载源码组件,将主类Application加载到Context中。这一过程是动态且高效的,确保了应用的快速启动和资源的有效管理。
至此,Spring Boot中ApplicationContext的准备阶段全面解析完成,从环境设置到启动类加载,每一个步骤都为ApplicationContext的高效运行打下了坚实的基础。接下来,我们将探讨ApplicationContext的刷新过程,敬请关注。
BeanWrapper
BeanWrapper 是 Spring 中一个关键的接口,在之前的 Spring 单例获取流程中我们已经见过它的身影。
PropertyDescriptor 我们在 Java 内省部分有详细介绍。
接下来,我们将逐一介绍它所继承的小孩溯源码溯源码接口。
PropertyEditorRegistry 是其中之一,要介绍这个接口,我们首先要了解 PropertyEditor。
PropertyEditor,俗称属性编辑器,最初只是在 GUI 中将字符串转换为 Java 对象相应类型的工具,例如将字符串转换为数值或布尔类型。Spring 在 JDK 原有的基础上也扩展了不少属性编辑器。
该接口非线程安全。
PropertyEditorSupport 是 PropertyEditor 的子类,由 JDK 提供。它方便我们继承该基础类,可以方便地扩展属性编辑器。
可以看到,一些常见的属性编辑器都是继承自它。
再回到我们的属性编辑器注册器,这是 Spring 提供的。
主要功能是注册对应类型的属性编辑器,比如将 Charset 和 CharsetEditor 注册在这里。
该类是继承自 PropertyEditorRegistry 并在里面帮我们注册了一些常用的类型以及对应的属性编辑器。
接下来,我们来看看 PropertyEditorRegistrar。
This is the central interface that a { @link PropertyEditorRegistrar} operates on.
它是专门操作 PropertyEditorRegistry 的。
作为 PropertyEditorRegistrar 的唯一子类,它会在你注册属性编辑器注册器的时候为你注册上一些常用的资源相关的属性编辑器。
这个类在 ApplicationContext 的 refresh 的 prepareBeanFactory 中被创建并赋值到 BeanFactory 中。
而 org.springframework.beans.PropertyEditorRegistrar#registerCustomEditors 方法在每次创建 bean 的时候都会被调起。
Spring 提供多类型转换器,子类实现该接口的同时一般也会实现 PropertyEditorRegistry 接口,当然这不是必须的。
因为类型转换器的实现是基于 PropertyEditor 的,而 PropertyEditor 是线程不安全的,所以 TypeConverter 也是线程不安全的。
这个基于 JDK PropertyEditor 的体系的命名方式都是 xxxSupport,这个抽象类不仅实现了 TypeConverter,还继承自 PropertyEditorRegistrySupport。
这个类主要是作为 BeanWrapperImpl 的基类。
该抽象类中存在一个成员变量 TypeConverterDelegate typeConverterDelegate,真正的转换工作是在它里面进行操作的。这个后续再看它里面的实现。
SimpleTypeConverter 是简单实现 TypeConverter 接口的类,跟 BeanWrapperImpl 的逻辑是一样的。同样它也是非线程安全的。
我们在获取 bean 的时候,如果有传入类型,并且在 bean 的类型和入参的不一致的时候,那么就会尝试进行转换。
PropertyAccessor 是一个观其名知其意的接口。
ConfigurablePropertyAccessor 继承自 PropertyAccessor 和 PropertyEditorRegistry,并实现了 TypeConverter 接口。
AbstractPropertyAccessor 实现了所有转换的方法,真正的属性访问的方法留给子类实现。
AbstractNestablePropertyAccessor 提供将对应的集合/数组的值给到目标对象的集合/数组的字段中的功能。
最终 BeanWrapperImpl 继承自 AbstractNestablePropertyAccessor,所以它具有访问属性以及进行相应类型的能力。
虽然我们在程序中很少直接使用 BeanWrapper,一般都是使用 BeanUtils 或者 BeanCopier。
再回到我们上面的 TypeConverterSupport 提及到的 TypeConverterDelegate。
从上面的代码中我们可以知道,Spring 在实现类型转换时,有两套机制,第一套机制依赖于 PropertyEditor,第二套机制依赖于 ConversionService。
关于属性编辑器 PropertyEditor 我们之前已经介绍过了,主要进行的是 String 到 Object 的转换。
正因为如此,属性编辑器进行类型转换有很大的局限性,所以 Spring 又推出了一套 ConversionService 的体系。
Spring 提供的从 S 类型转换到 T 类型的转换器是 ConversionServiceConverter。
为了方便能够将 S 转为一系列的 T 类型,Spring 提供了 ConverterFactory。
转换器的注册器是 ConverterRegistry。
相当于 Registrar 的功能,ConversionService 是线程安全的。
其实可以从 Converter 的定义可以看出,Converter 是无状态的,而不像 PropertyEditor。
在 SpringApplication 的 run 方法的 prepareEnvironment 的 configureEnvironment 中创建了 ApplicationConversionService 并添加了各种常见的转换器。
最后,其实这篇文章只是单纯地了解关于 PropertyEditor 和 ConversionServer 的知识,并没有从源码详细说明 Spring 怎么使用它们。
这个可能放到以后的文章。这篇文章单纯是补全这个主题的基础知识,为后面继续看 Spring 的代码进行铺垫。