文档说明:
开发自动配置和使用条件
如果您在开发共享库的公司工作,或者您在开源或商业库中工作,则可能需要开发自己的自动配置。自动配置类可以捆绑在外部jar中,仍然可以通过Spring Boot获取。
如果我有其他所有注释(甚至@AutoConfigureAfter或@AutoConfigureBefore注释),
为什么要将属性文件维护为指向带注释的类?
答案 0 :(得分:14)
因为我们不会扫描世界以确定项目中存在哪些自动配置类。首先,自动配置只是一个常规@Configuration
类。
找到Spring组件的方式是通过显式声明或组件扫描,但我们需要在实际启动上下文之前知道自动配置类的列表。
答案 1 :(得分:0)
启动SpringBoot应用程序时,它不会扫描jar中的所有类,因此SpringBoot启动程序应指定自动配置的类。例如,在spring-boot-2.0.4.RELEASE中,它的初始化如下:
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
//1. method run will call the construtor below
SpringApplication.run(MyApplication.class, args);
}
}
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = deduceWebApplicationType();
//2. find all the classes whose key is ApplicationContextInitializer in spring.factories and initialize them
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
...
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,
Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
// Use names and ensure unique to protect against duplicates
Set<String> names = new LinkedHashSet<>(
//3. use current thread classcloader to load resources in the classpath
SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
//SpringFactoriesLoader.java
public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
// 3.1 first find the configuration file
return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
}
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
...
try {
Enumeration<URL> urls = (classLoader != null ?
// public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
//4. spring.factories file is defined here
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
result = new LinkedMultiValueMap<>();
...
}
答案 2 :(得分:0)
spring.factories中的所有条目均通过以下方法加载-
org.springframework.boot.autoconfigure.ImportAutoConfigurationImportSelector#loadFactoryNames
protected Collection<String> loadFactoryNames(Class<?> source) {
return SpringFactoriesLoader.loadFactoryNames(source, getClass().getClassLoader());
}
SpringFactoriesLoader属于spring-core库,请参见下面的屏幕截图