spring.factories文件
本文涉及spring-boot版本为2.1.6.RELEASE
在阅读spring-boot相关源码时,常常见到spring.factories文件,里面写了自动配置(AutoConfiguration)相关的类名,因此产生了一个疑问:“明明自动配置的类已经打上了@Configuration的注解,为什么还要写spring.factories文件?”
这个话题需要从@SpringBootApplication注解开始说起。
查看@SpringBootApplication源码,我们能看到继承的以下注解:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
……
}
其中比较重要的是@EnableAutoConfiguration和@ComponentScan两个注解。@ComponentScan注解的作用是扫描@SpringBootApplication所在的Application类(即spring-boot项目的入口类)所在的包(basepackage)下所有的@component注解(或拓展了@component的注解)标记的bean,并注册到spring容器中。
看到这里也许会有个疑问,在spring-boot项目中pom文件里面添加的依赖中的bean(spring-boot项目外的bean)是如何注册到spring-boot项目的spring容器中的呢?
这就需要讨论@EnableAutoConfiguration的作用。查看@EnableAutoConfiguration源码,
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
我们可以看到比较关键的代码是@Import(AutoConfigurationImportSelector.class),而AutoConfigurationImportSelector.class做了什么呢?通过其源码可以看出关键的部分为,
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
其中,getAutoConfigurationEntry方法获取了spring-boot项目中需要自动配置的项(bean),查看其源码发现,
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
其中最重要的部分为getCandidateConfigurations方法,它获取了所有可能参与到项目的候选配置bean,与之对应的,getExclusions获取了所有不需要加载的配置bean。进一步查看getCandidateConfigurations方法的源码,
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
这个方法的具体实现为,读取spring-boot项目的classpath下META-INF/spring.factories的内容,这个文件常常以K/V的形式存储数据,例如:
# Auto Configuration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.HelloAutoConfiguration,\
……
getCandidateConfigurations方法获取需要自动配置的类,除去上面讲到的需要排除(exclude)的配置类,其他类将会注册到spring-boot项目的spring容器中。
看到这里,想必已经了解@EnableAutoConfiguration注解的工作原理,回到最初的话题,“为什么要写spring.factories文件?”
结合前面提出的疑问——“在spring-boot项目中pom文件里面添加的依赖中的bean是如何注册到spring-boot项目的spring容器中的呢?”,不难得出spring.factories文件是帮助spring-boot项目包以外的bean(即在pom文件中添加依赖中的bean)注册到spring-boot项目的spring容器的结论。由于@ComponentScan注解只能扫描spring-boot项目包内的bean并注册到spring容器中,因此需要@EnableAutoConfiguration注解来注册项目包外的bean。而spring.factories文件,则是用来记录项目包外需要注册的bean类名。
spring.factories文件相关推荐
- spring.factories 文件配置详情
使用场景 在程序开发中,可能会出现包名不一样的情况(如:pom 依赖的很多的 jar),如何解决Spring Boot不能被默认路径扫描呢? 方法一:在 Spring Boot Application ...
- META-INF/spring.factories文件的作用是什么
META-INF/spring.factories文件的作用是什么 这片文章中会找到你想要的答案. *看一个SpringBoot入口类 package com.example.multithread; ...
- SpringBoot解耦的扩展机制 Spring Factories介绍及使用
一.什么是 SPI机制 Spring Boot中有一种非常解耦的扩展机制:Spring Factories.这种扩展机制实际上是仿照Java中的SPI扩展机制来实现的.SPI的全名为Service P ...
- spring.factories 的妙用
现象 在阅读 Spring-Boot 相关源码时,常常见到 spring.factories 文件,里面写了自动配置(AutoConfiguration)相关的类名,因此产生了一个疑问:"明 ...
- Spring Boot 之 spring.factories的用法
原因 为什么要使用,因为在程序开发中,可能包名不一样,pom依赖的很多的jar 他们是如何把这些类进行注入到spring容器中的呢. 所以springboot就提出了spring.factories ...
- SpringBoot加载spring.factories的价值
SpringBoot加载spring.factories的价值 在springboot的各个依赖包下,我们经常看到META-INF/spring.factories这个文件.spring.factor ...
- spring.factories 的基本使用
spring.factories 的基本作用 在若依-微服务版的源码学习中,发现项目中多次用到了 spring.factories .因此记录一下自己的学习总结: 参考博客: spring.facto ...
- spring.factories详解
在Spring Boot中有一种非常解耦的扩展机制:Spring Factories.这种扩展机制实际上是仿照Java中的SPI扩展机制来实现的. Java SPI机制SPI的全名为Service P ...
- Spring Factories机制
Spring Factories机制简述 Spring Factories机制和Java SPI的扩展机制类似,Spring Boot采用了spring.factories的扩展机制,在很多sprin ...
最新文章
- Java开发人员 2019 生态系统信息图
- SAP HANA 三大特点
- 字符编码:ASCII,Unicode(UTF-8)
- halcon file_exists 检查文件是否存在
- eslint vscode 自动格式化_使用 VSCode 的必备三大神器,这才是开发 Vue 的真香解决方案...
- 起到的C++是中间层的作用
- 活动预告丨openGauss西安Meetup来啦!本周五见!
- 关于div的定位属性问题
- python encode和decode函数说明
- cin cout加快
- bzoj 1296: [SCOI2009]粉刷匠(DP+DP)
- android新闻客户端实验报告,基于Android平台的新闻客户端设计与实现
- 区分 点操作符+属性名 和 getAttribute()
- 如何查看CentOS版本方法
- 成都电子地图 高清15、17、19级别 谷歌电子地图资源
- IDEA开发工具当前窗口导入多个项目
- 爱数私有云盘 AnyShare 部署(二)
- 解决QFontDatabase: Cannot find font directory XXX/lib/fonts
- [oracle]Oracle数据库安全管理
- T13656 NOI接站
热门文章
- PL/SQL Developer操作界面查看oracle数据库版本
- android表情符号使用,关于android:表情符号符号?? 在string.xml中使应用程序崩溃
- win10的哪个版本最好用?
- Windows 更新后 VMware workstation Pro 软件无法打开
- 南方的朋友请回避一下,我给北方的朋友介绍一下我们南方的臭豆腐 ——《带头双向循环链表》
- Mint UI —— 基于 Vue.js 的移动端组件库
- 7034mysql意外停止_中国名创解决mysql数据库意外自动关闭(停止)的问题
- Grafana WorldMap
- 8710系列的BW14模组,共模体型
- 盘点10个冷门Python库,原来Python还能实现这些功能?