AutoConfiguration加载元数据和自动配置组件

简介: @EnableAutoConfiguration 加载元数据配置加载元数据配置主要是为后续操作提供数据支持。我们先来看加载相关源代码的具体实现,该功能的代码依旧日在 selectlmpots 方法内。@OverridepublicString[] selectImports (AnnotationMetadata annotationMetadata) {AutoConfigurat ionMetadata autoConf igurationMetadata = AutoConfigurationMetadataLoader. loadMetadata(this. bea
@EnableAutoConfiguration 加载元数据配置
加载元数据配置主要是为后续操作提供数据支持。
我们先来看加载相关源代码的具体实现,该功能的代码依旧日在 selectlmpots 方法内。
@Override
publicString[] selectImports (AnnotationMetadata annotationMetadata) {
AutoConfigurat ionMetadata autoConf igurationMetadata = AutoConfigurationMetadataLoader. loadMetadata(this. beanClassLoader);
}

加载元数据的配置用到了AutoConfigurationMetadataLoader类提供的loadMetaData方法,该方法会默认加载类路径下 META-INF/springautoconfigure-metadata.properties 内的配置。


final class AutoConfigurationMetadataLoader {
//默认加载元数据的路径protected static final String PATH ="META- INF/spring- autoconfigure - metadata.
properties";
//默认调用改方法,传入默认 PATHstatic AutoConfigurat ionMetadata loadMetadata(ClassLoader classLoader )returnloadMetadata(classLoader, PATH);
static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader, Stringpath) {try//获取数据存储 FEnumeration 中Enumeration urls = (classLoader != null) ? classLoader . getResources(path)
: ClassLoader . getSys temResources(path);
Properties properties = new Properties();while(urls.hasMoreElements()) {
//遍历 Enumeration 中的 URL,加载其中的属性, 存储到 Properties 中properties . putAll(PropertiesLoaderUtils. loadProperties (new UrlResource(urls .nextElement())));}returnloadMetadata(properties);
} catch (IOException ex) {throw new IllegalArgumentException("Unable to load @ConditionalOnClas
; location ["+path+"]",ex);
//创建 AutoConfigurat ionMe tadata 的实现类 PropertiesAutoConf igurat ionMetadatstatic AutoConfigurationMetadata loadMetadata(Properties properties) {returnnew PropertiesAutoConfigurationMetadata(properties);
// AutoConfigurationMetadata 的内部实现类private static class PropertiesAutoConfigurationMetadata implements AutoCon-figurat ionMetadata {。。。}。。。}

在上面的代码中 AutoConfigurationMetadataLoader 调用 ladMetadaClassLoadar cassLoaden)方法,会获取默认变量 PATH 指定的文件,然后加载并存储于 Enumeration 数据结构中。随后从变量 PATH 指定的文件中获取其中配置的属性存诸 Poperties 内,最终调用在该类内部实现的 AutoConfigurationMetadata 的子类的构造方法。

spring-autoconfigure-metadata.properties 文件内的配置格式如下。

自动配置类的全限定名.注解名称=值


如果 spnaotningre-etadata properties 文件内有多个值,就用英文逗号分隔,例如:

org. springframework . boot . autoconfigure .data. jdbc . IdbcRepositoriesAutoConfiguration . ConditionalOnClass=org. springframework.data. jdbc . repos itory. config.JdbcConfigurat ion, org. springframework. jdbc . core . namedpar am .NamedParameterJdbcOperations
。。。

为什么要加载此元数据呢?加载元数据主要是为了后续过滤自动配置使用。Spring Boot 使用-Annlation 的处理器来收集自动加载的条件,这些条件可以在元数据文件中进行配置。SpingBoot 会将收集好的 C@Confguration 进行一 次过滤,进而剔除不满足条件的配置类。

在官方文档中已经明确指出,使用这种配置方式可以有效缩短 SpringBoot 的启动时间,减少@oniguraio 类的数量,从而减少初始化 ean 的耗时。后续章节中我们会看到过滤自动配置的具体使用方法。


image.png

@EnableAutoConfiguration 加载自动配置 组件

加载自动配置组件是自动配置的核心组件之一,这些自动配置组件在类路径中 METAINF 目录下的 Ssping fctories 文件中进行注册。Spring Boof 预置了-部分常用组件,如果我们需要创建自己的组件,可参考 SpringBoot 预置组件在自己的 Starters 中进行配置,在后面的章节中会专门对此进行讲解。

通过 Sping Core 提供的 Soingacaorestoaodar 类可以读取 spring. fctories 文件中注册的类。下面我们通过源代码来看一下如何在 AutoConfigurationlmportSelector 类中通过 getCateConfigurations 方法来读取 spring.factories 文件中注册的类。


protectedList getCandidateConfigurations(Annotat ionMetadata metadata,
AnnotationAttributes attr
ibutes){
List configurations = SpringFactoriesLoader .loadFactoryNames(
getSpringFactoriesLoaderFactoryClass(),getBeanClassLoader());
Assert. notEmpty (configurations ,"No auto configuration classes found in META-INF/spring.f
actories. If you
+ "areusinga custom packaging, make sure that fileisC
orrect.");
return configurations;
protected Class<?> getSpringF actoriesLoaderFactoryClass() {
return EnableAutoConfiguration.class;
}

getCandidateConfigurations 方 法 使 用 SpringFactoriesL oader 类 提 供 的loadFactoryNames 方法来读取 META-INF/spring.factories 中的配置。如果程序未读取到任何 配 置 内 容 , 会 抛 出 异 常 信 息 。 而 loadFactoryNames 方 法 的 第 一 个 参 数 为getSpringFactoriesL oaderFactoryClass 方法返回的 EnableAutoConfiguration.class,也就是说 loadFactoryNames 只会读取配置文件中针对自动配置的注册类。

SpringFactoriesLoader 类的 loadFactoryNames 方法相关代码如下。

public final class SpringFactoriesLoader {
//概类加载文件的路径, 可能存在多个
public static final String FACTORIES_RESOURCE LOCATION ="META- INF/spring. factories";
//加载所有的 META- INF/spring. factories.文件,封装成 Map, 并从中获取指定类名的列表
public static List loadFactoryNames(Class factoryClass, @Nullable ClassLoader classLoader) {String factoryClassName = factoryClass . getName();returnloadSpringFactories (classLoader) . getOrDefault(factoryClassName ,
Collections . emptylist());//加载所有的 META- INF/spring. factories 文件,封装成 Map, Key 为接口的全类名,Valu
e 为对应配置值的 ist 集合private static Map> loadSpringFactories (@Nullable ClassLoader classLoader) {MultiValueMap result = cache.get(classLoader);if(result != null) {
returnresult;
try {Enumeration urls = (classLoader != null ?classLoader . getResources(FACTORIES_RESOURCE_LO
CATION) :ClassLoader . getSystemResources (FACTORIES_RESOU
RCE_LOCATION));
result = new LinkedMultiValueMap<>();while(urls .hasMoreElements()) {
URL url = urls .nextElement();UrlResource resource = new UrlResource(url);Properties properties = PropertiesLoaderUtils . loadProperties ( resource);for(Map.Entry entry : properties .entrySet()) {
String factoryClassName = ((String) entry . getKey()).trim();for(String factoryName : StringUtils . commaDelimitedL istTo-
StringArray((String) entry.getValue())) {result . add(factoryClassName, factoryName . trim());cache. put(classLoader, result);returnresult;
} catch (I0Exception ex)throw new IllegalArgumentException("Unable to load factories from location ["+
FACTORIES_RESOURCE__LOCATION +"]",e
x);}}。。。}

简单描述以上加载的过程就是: SpringFactoriesLoader 加载 器加载指定 ClassL oader 下面的所有 META-INF/spring.factories 文件,并将文件解析内容存于 Map<String,List<String>>内。然后,通过 loadFactoryNames 传递过来的 class 的名称从 Map 中获得该类的配置列表。

结 合 下 面 spring.factories 文 件 的 内 容 格 式 , 我 们 可 以 更 加 清 晰 地 了 解Map<String,List<String>>中都存储了什么。

# Auto Configure
org. springframework . boot . autoconfigure . EnableAutoConf iguration=\
org. springframework . boot . autoconfigure . admin. Spr ingApplicat ionAdminJmxAutoC
onfig :
uration, \
org. springframework . boot . autoconfigure . aop . AopAutoConfiguration, \
org . springframework . boot . autoconfigure . amqp . RabbitAutoConfiguration, \
org. springframework . boot. autoconfigure . batch . BatchAutoConfiguration,\
org. springfr amework . boot . autoconfigure . cache . CacheAutoConfiguration, \
org. springframework . boot . autoconfigure . cassandra . CassandraAutoConfiguratio
n,\
。。。

以上代码仅以 EnableAutoConfiguration 配置的部分内容为例,spring.factories 文件的基本格式为自动配置类的全限定名=值,与 2.3.5 节中介绍的元数据的格式很相似,只不过缺少了“,注解名称”部分,如果包含多个值,用英文逗号分隔。

我们继续以 EnableAutoConfiguration 的配置为例 Map<String,List<String>>内存储的对应数据就是key值为\/nliin/古org.springframework.boot.autoconfigure .EnableAutoConfiguration,Value 值为其等号后面以分号分割的各种 AutoConfiguration 类。

当然,spring.factories 文件内还有其他的配置,比如用于监听的 Listeners 和用于过滤的Filters 等。很显然,在加载自动配置组件时,此方法只用到了 EnableAutoConfiguration 对应的配置。

因为程序默认加载的是 ClassLoader 下面的所有 META-INF/spring.factories文件中的配置,所以难免在不同的 jar 包中出现重复的配置。我们可以在源代码中使用 Set 集合数据不可重复的特性进行去重操作。

protectedfinalList removeDuplicates(Listlist) {
returnnewArrayList<>(newLinkedHashSet<>(list));
}


相关文章
|
分布式计算 大数据 Hadoop
大数据||zookeeper来实现HDFS自动故障转移
namenode启动都是standby。 利用zookeeper来选举一个为active ZooKeeper客户端ZKFC: ZKFailoverController 给namenode添加失效备缓监控器(ZKFC: ZKFailoverCon...
1755 0
|
机器学习/深度学习 PyTorch 算法框架/工具
在阿里云机器学习平台上布置一个PyTorch模型
在阿里云机器学习平台上布置一个PyTorch模型【1月更文挑战第21天】【1月更文挑战第105篇】
393 1
|
网络安全 数据库 数据可视化
HeidiSQL使用SSH Tunnel连接数据库
HeidiSQL SSH Tunnel登录远程数据库服务
4638 0
|
弹性计算 Ubuntu Linux
幻兽帕鲁在阿里云上的快速部署教程(持续更新)
幻兽帕鲁最近非常火,是一款支持多人游戏模式的全新开放世界生存制作游戏。在广阔的世界中收集神奇的生物“帕鲁”,派他们进行战斗、建造、做农活,工业生产等。 游戏推出自己搭建服务器形式,针对大陆用户,想抢先体验的,并通过加速连接官方服务器节点体验游戏。如果你想要快速上手幻兽帕鲁,快速完成资源和环境部署,可以参考本教程实操验证。 零代码,在10-15分钟内一键完成环境和应用搭建 事前校验和计价,按量使用(本方案消费约0.724元/时) 体验完后还可以一键释放
10882 5
|
JavaScript 前端开发
Vue、ElementUI配合Node、multiparty模块实现图片上传并反显_小demo
如何使用Vue和Element UI配合Node.js及multiparty模块实现图片上传并反显的功能,包括前端的Element UI组件配置和后端的Node.js服务端代码实现。
181 1
Vue、ElementUI配合Node、multiparty模块实现图片上传并反显_小demo
|
存储 弹性计算 缓存
阿里云服务器通用算力型实例规格性能、适用场景及价格参考
通用算力型云服务器阿里云推出的一款高性价比系列云服务器产品,也是目前阿里云官网活动中比较推荐用户购买的云服务器产品,目前通用算力型云服务器的活动价格略高于经济型e实例,但又比计算型c7、通用型g7等其他系列的云服务器价格要低一些,本文通过介绍通用算力型云服务器的性能、产品优势及适用场景和价格等情况,从而让大家了解通用算力型云服务器,对是否选择通用算力型云服务器做一个参考。
1352 1
阿里云服务器通用算力型实例规格性能、适用场景及价格参考
|
11月前
|
应用服务中间件 网络安全 数据安全/隐私保护
【赵渝强老师】使用Docker Machine远程管理Docker
Docker Machine 是 Docker 官方提供的远程管理工具,可帮助开发人员在远程主机或虚拟机上安装和管理 Docker 环境。本文介绍了如何在远程主机上安装 Docker 并配置免密码登录,以及使用 Docker Machine 管理远程 Docker 主机的常用命令。
259 0
|
Java 数据库连接 mybatis
mybatis注解@Select中添加判断条件<script>
mybatis注解@Select中添加判断条件<script>
1043 0
|
PHP 数据库
laravel表单验证的exists、unique去除软删除字段的校验
虽然Laravel的验证系统非常强大和灵活,但在处理软删除数据时仍需要特别注意。通过正确使用验证规则,并在需要时创建自定义验证规则,你可以确保应用的数据验证既准确又高效。记得在对 `unique`和 `exists`规则进程自定义时,清晰地注明你排除软删除记录的意图,这将使得代码更容易理解和维护。
334 4
|
Java Spring 容器
Spring注解开发,bean的作用范围及生命周期、Spring注解开发依赖注入
Spring注解开发,bean的作用范围及生命周期、Spring注解开发依赖注入
166 1
Spring注解开发,bean的作用范围及生命周期、Spring注解开发依赖注入