Spring Factories如何实现自动配置?
- 内容介绍
- 文章标签
- 相关推荐
本文共计2284个文字,预计阅读时间需要10分钟。
在阅读本章内容前,建议您先了解Java的SPI状态,因为Spring的Factories实际上是Spring版本的Java SPI。我在关于Java基础系列文章中详细介绍了Java SPI机制。Spring Factories最重要的功能是。
在看本节文章之前,建议大家先去了一下java的SPI状态,因为Spring的Factories就是Spring版本的Java Spi,我在关于java基础系列文章中有详细介绍Java SPI机制。 Spring Factories的最重要的功能就是:可以通过配置文件指定Spring容器加载一些特定的组件。
基本概念
什么是Spring Factories Spring Factories是一种类似于Java SPI的机制,它在META-INF/spring.factories文件中配置接口的实现类名称,然后在程序中读取这些配置文件并实例化。
引用自博客:Java SPI 主要是应用于厂商自定义组件或插件中。在java.util.ServiceLoader的文档里有比较详细的介绍。简单的总结下java SPI机制的思想:我们系统里抽象的各个模块,往往有很多不同的实现方案,比如日志模块、xml解析模块、jdbc模块等方案。面向的对象的设计里,我们一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。一旦代码里涉及具体的实现类,就违反了可拔插的原则,如果需要替换一种实现,就需要修改代码。为了实现在模块装配的时候能不在程序里动态指明,这就需要一种服务发现机制。 Java SPI就是提供这样的一个机制:为某个接口寻找服务实现的机制。有点类似IOC的思想,就是将装配的控制权移到程序之外,在模块化设计中这个机制尤其重要。
为什么要有Spring Factories
Spring Factories机制提供了一种解耦容器注入的方式,帮助外部包(独立于spring-boot项目)注册Bean到spring boot项目容器中。
问题:如果想要被Spring容器管理的Bean的路径不再Spring Boot 项目的扫描路径下,那该怎么办呢?
普通解法1:在Spring Boot 项目中配置ComponentScan注解的扫描路径,添加需要被扫描的方法。
普通解法2:通过在Spring Boot 项目中添加@EnableAutoConfiguration注解,并自定义@EnableXXXXConfiguration的注解,通过注解中的方法注入Bean。 普通解法3:在Spring Boot项目中xxxx.................。
这些解法主要思想都如下图所示,虽然已经实现了帮助外部包(独立于spring-boot项目)注册Bean到spring boot项目容器中的功能,但是Spring Boot 项目都需要知道外部包的信息,并在其代码中引入外部包的相关逻辑,如果外部包变更的情况下,Spring Boot 项目也需要跟着变更,Spring Boot和外部包实现直接存在紧耦合关系。
Spring包依赖
Spring Factories机制解法:
在外部包的META-INF/spring.factories文件中添加配置文件,Spring Boot项目会自动扫描这个配置文件,获取外部包的Bean的详细信息。基本思想如下图所示,从图中可以看到,Spring Boot项目中已经不包含外部包的相关逻辑,实现与外部包之间的解耦关系。
Spring的SPI
Spring Factories机制原理
核心类SpringFactoriesLoader
从上文可知,Spring Factories机制通过META-INF/spring.factories文件获取相关的实现类的配置信息,而SpringFactoriesLoader的功能就是读取META-INF/spring.factories,并加载配置中的类。SpringFactoriesLoader主要有两个方法:loadFactories和loadFactoryNames。
SpringFactoriesLoader官方说明 : General purpose factory loading mechanism for internal use within the framework.
META-INF/spring.factories中定义了实现类和对应的接口之间的关系,其定义格式如下:
example.MyService=example.MyServiceImpl1,example.MyServiceImpl2 其中的example.MyService为接口全称,example.MyServiceImpl1,example.MyServiceImpl2为两个实现类的全称。
官方说明: SpringFactoriesLoader loads and instantiates factories of a given type from META-INF/spring.factories files which may be present in multiple JAR files in the classpath. The file must be in {@link Properties} format, where the key is the fully qualified name of the interface or abstract class, and the value is a comma-separated list of implementation class names. For example: example.MyService=example.MyServiceImpl1,example.MyServiceImpl2 where {@code example.MyService} is the name of the interface, and {@code MyServiceImpl1} and {@code MyServiceImpl2} are two implementations.
loadFactoryNames
在这个方法中会遍历整个ClassLoader中所有jar包下的spring.factories文件。通过Properties解析所有接口的实现类名称。
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
String factoryTypeName = factoryType.getName();
return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}
loadFactories
loadFactories方法首先调用loadFactoryNames方法获取待实例化的具体实现类的全称,然后调用instantiateFactory方法实例化每一个具体实现类,最终返回一个具体实现类的实例列表。
public static <T> List<T> loadFactories(Class<T> factoryType, @Nullable ClassLoader classLoader) {
Assert.notNull(factoryType, "'factoryType' must not be null");
ClassLoader classLoaderToUse = classLoader;
if (classLoaderToUse == null) {
classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
}
//调用loadFactoryNames获取接口的实现类
List<String> factoryImplementationNames = loadFactoryNames(factoryType, classLoaderToUse);
if (logger.isTraceEnabled()) {
logger.trace("Loaded [" + factoryType.getName() + "] names: " + factoryImplementationNames);
}
//遍历 factoryNames 数组,创建实现类的对象
List<T> result = new ArrayList<>(factoryImplementationNames.size());
for (String factoryImplementationName : factoryImplementationNames) {
//调用instantiateFactory根据类创建实例对象
result.add(instantiateFactory(factoryImplementationName, factoryType, classLoaderToUse));
}
//排序
AnnotationAwareOrderComparator.sort(result);
return result;
}
Spring Boot 默认的Factories
Spring boot中默认使用了很多factories机制,主要包含:
自定义Spring Factories机制
本节将使用一个例子来展示Spring Factories机制,案例分为两个项目spring-factories-provider和spring-factories-consume,其中spring-factories-consume可以类比于上文中的Spring Boot项目,包含Bean的接口和Bean的调用,spring-factories-provider可以类比于外部包,包含了bean的实现。项目目录结构如下:
Spring Factories机制
以下为各个文件的内容:
@Service
public class PrintDemoService {
@PostConstruct
public void printService(){
List<String> serviceNames = SpringFactoriesLoader.loadFactoryNames(DemoService.class,null);
for (String serviceName:serviceNames){
System.out.println(serviceName);
}
List<DemoService> services = SpringFactoriesLoader.loadFactories(DemoService.class,null);
for (DemoService demoService:services){
demoService.printName();
}
}
public class DemoServiceImpl1 implements DemoService {
@Override
public void printName() {
System.out.println("This is in demo 1.");
}
}
public class DemoServiceImpl1 implements DemoService {
@Override
public void printName() {
System.out.println("This is in demo 1.");
}
}
public class DemoServiceImpl2 implements DemoService {
@Override
public void printName() {
System.out.println("This is in demo 2.");
}
}
@SpringBootApplication
public class FactoriesApplication {
public static void main(String[] args) {
SpringApplication.run(FactoriesApplication.class, args);
}
}
com.wangzemin.learning.factories.interfac.DemoService=\
com.wangzemin.learning.factories.impl.DemoServiceImpl1,\
com.wangzemin.learning.factories.impl.DemoServiceImpl2
程序的运行结果如下图所示,可以看到,Factories机制已经成功发挥作用。
在这里插入图片描述
附录:spring boot 自带factories文件示例
# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer
# Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener
# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnBeanCondition,\
org.springframework.boot.autoconfigure.condition.OnClassCondition,\
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.blog.csdn.net/dieaixia5129/article/details/126081613
blog.csdn.net/curtinliu/article/details/111588917
本文共计2284个文字,预计阅读时间需要10分钟。
在阅读本章内容前,建议您先了解Java的SPI状态,因为Spring的Factories实际上是Spring版本的Java SPI。我在关于Java基础系列文章中详细介绍了Java SPI机制。Spring Factories最重要的功能是。
在看本节文章之前,建议大家先去了一下java的SPI状态,因为Spring的Factories就是Spring版本的Java Spi,我在关于java基础系列文章中有详细介绍Java SPI机制。 Spring Factories的最重要的功能就是:可以通过配置文件指定Spring容器加载一些特定的组件。
基本概念
什么是Spring Factories Spring Factories是一种类似于Java SPI的机制,它在META-INF/spring.factories文件中配置接口的实现类名称,然后在程序中读取这些配置文件并实例化。
引用自博客:Java SPI 主要是应用于厂商自定义组件或插件中。在java.util.ServiceLoader的文档里有比较详细的介绍。简单的总结下java SPI机制的思想:我们系统里抽象的各个模块,往往有很多不同的实现方案,比如日志模块、xml解析模块、jdbc模块等方案。面向的对象的设计里,我们一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。一旦代码里涉及具体的实现类,就违反了可拔插的原则,如果需要替换一种实现,就需要修改代码。为了实现在模块装配的时候能不在程序里动态指明,这就需要一种服务发现机制。 Java SPI就是提供这样的一个机制:为某个接口寻找服务实现的机制。有点类似IOC的思想,就是将装配的控制权移到程序之外,在模块化设计中这个机制尤其重要。
为什么要有Spring Factories
Spring Factories机制提供了一种解耦容器注入的方式,帮助外部包(独立于spring-boot项目)注册Bean到spring boot项目容器中。
问题:如果想要被Spring容器管理的Bean的路径不再Spring Boot 项目的扫描路径下,那该怎么办呢?
普通解法1:在Spring Boot 项目中配置ComponentScan注解的扫描路径,添加需要被扫描的方法。
普通解法2:通过在Spring Boot 项目中添加@EnableAutoConfiguration注解,并自定义@EnableXXXXConfiguration的注解,通过注解中的方法注入Bean。 普通解法3:在Spring Boot项目中xxxx.................。
这些解法主要思想都如下图所示,虽然已经实现了帮助外部包(独立于spring-boot项目)注册Bean到spring boot项目容器中的功能,但是Spring Boot 项目都需要知道外部包的信息,并在其代码中引入外部包的相关逻辑,如果外部包变更的情况下,Spring Boot 项目也需要跟着变更,Spring Boot和外部包实现直接存在紧耦合关系。
Spring包依赖
Spring Factories机制解法:
在外部包的META-INF/spring.factories文件中添加配置文件,Spring Boot项目会自动扫描这个配置文件,获取外部包的Bean的详细信息。基本思想如下图所示,从图中可以看到,Spring Boot项目中已经不包含外部包的相关逻辑,实现与外部包之间的解耦关系。
Spring的SPI
Spring Factories机制原理
核心类SpringFactoriesLoader
从上文可知,Spring Factories机制通过META-INF/spring.factories文件获取相关的实现类的配置信息,而SpringFactoriesLoader的功能就是读取META-INF/spring.factories,并加载配置中的类。SpringFactoriesLoader主要有两个方法:loadFactories和loadFactoryNames。
SpringFactoriesLoader官方说明 : General purpose factory loading mechanism for internal use within the framework.
META-INF/spring.factories中定义了实现类和对应的接口之间的关系,其定义格式如下:
example.MyService=example.MyServiceImpl1,example.MyServiceImpl2 其中的example.MyService为接口全称,example.MyServiceImpl1,example.MyServiceImpl2为两个实现类的全称。
官方说明: SpringFactoriesLoader loads and instantiates factories of a given type from META-INF/spring.factories files which may be present in multiple JAR files in the classpath. The file must be in {@link Properties} format, where the key is the fully qualified name of the interface or abstract class, and the value is a comma-separated list of implementation class names. For example: example.MyService=example.MyServiceImpl1,example.MyServiceImpl2 where {@code example.MyService} is the name of the interface, and {@code MyServiceImpl1} and {@code MyServiceImpl2} are two implementations.
loadFactoryNames
在这个方法中会遍历整个ClassLoader中所有jar包下的spring.factories文件。通过Properties解析所有接口的实现类名称。
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
String factoryTypeName = factoryType.getName();
return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}
loadFactories
loadFactories方法首先调用loadFactoryNames方法获取待实例化的具体实现类的全称,然后调用instantiateFactory方法实例化每一个具体实现类,最终返回一个具体实现类的实例列表。
public static <T> List<T> loadFactories(Class<T> factoryType, @Nullable ClassLoader classLoader) {
Assert.notNull(factoryType, "'factoryType' must not be null");
ClassLoader classLoaderToUse = classLoader;
if (classLoaderToUse == null) {
classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
}
//调用loadFactoryNames获取接口的实现类
List<String> factoryImplementationNames = loadFactoryNames(factoryType, classLoaderToUse);
if (logger.isTraceEnabled()) {
logger.trace("Loaded [" + factoryType.getName() + "] names: " + factoryImplementationNames);
}
//遍历 factoryNames 数组,创建实现类的对象
List<T> result = new ArrayList<>(factoryImplementationNames.size());
for (String factoryImplementationName : factoryImplementationNames) {
//调用instantiateFactory根据类创建实例对象
result.add(instantiateFactory(factoryImplementationName, factoryType, classLoaderToUse));
}
//排序
AnnotationAwareOrderComparator.sort(result);
return result;
}
Spring Boot 默认的Factories
Spring boot中默认使用了很多factories机制,主要包含:
自定义Spring Factories机制
本节将使用一个例子来展示Spring Factories机制,案例分为两个项目spring-factories-provider和spring-factories-consume,其中spring-factories-consume可以类比于上文中的Spring Boot项目,包含Bean的接口和Bean的调用,spring-factories-provider可以类比于外部包,包含了bean的实现。项目目录结构如下:
Spring Factories机制
以下为各个文件的内容:
@Service
public class PrintDemoService {
@PostConstruct
public void printService(){
List<String> serviceNames = SpringFactoriesLoader.loadFactoryNames(DemoService.class,null);
for (String serviceName:serviceNames){
System.out.println(serviceName);
}
List<DemoService> services = SpringFactoriesLoader.loadFactories(DemoService.class,null);
for (DemoService demoService:services){
demoService.printName();
}
}
public class DemoServiceImpl1 implements DemoService {
@Override
public void printName() {
System.out.println("This is in demo 1.");
}
}
public class DemoServiceImpl1 implements DemoService {
@Override
public void printName() {
System.out.println("This is in demo 1.");
}
}
public class DemoServiceImpl2 implements DemoService {
@Override
public void printName() {
System.out.println("This is in demo 2.");
}
}
@SpringBootApplication
public class FactoriesApplication {
public static void main(String[] args) {
SpringApplication.run(FactoriesApplication.class, args);
}
}
com.wangzemin.learning.factories.interfac.DemoService=\
com.wangzemin.learning.factories.impl.DemoServiceImpl1,\
com.wangzemin.learning.factories.impl.DemoServiceImpl2
程序的运行结果如下图所示,可以看到,Factories机制已经成功发挥作用。
在这里插入图片描述
附录:spring boot 自带factories文件示例
# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer
# Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener
# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnBeanCondition,\
org.springframework.boot.autoconfigure.condition.OnClassCondition,\
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.blog.csdn.net/dieaixia5129/article/details/126081613
blog.csdn.net/curtinliu/article/details/111588917

