入口:AbstractApplicationContext的refresh方法
在其invokeBeanFactoryPostProcessors方法中,会找到所有需要加载的类,并且为之排序,根据类加载条件来放弃加载
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
//在这里会找到所有需要加载的类(不仅仅是自动配置的类),并且为之排序,根据类加载条件来放弃加载
invokeBeanFactoryPostProcessors(beanFactory);
在AutoConfigurationImportSelector的getCandidateConfigurations方法里读取所有自动配置类
通过SpringFactoriesLoader的loadFactoryNames方法,可以看见在loadSpringFactories里面读取META-INF/spring.factories配置
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
}
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
MultiValueMap<String, String> result = cache.get(classLoader);
if (result != null) {
return result;
}
try {
//读取META-INF/spring.factories
Enumeration<URL> urls = (classLoader != null ?
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_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.commaDelimitedListToStringArray((String) entry.getValue())) {
result.add(factoryClassName, factoryName.trim());
}
}
}
cache.put(classLoader, result);
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load factories from location [" +
FACTORIES_RESOURCE_LOCATION + "]", ex);
}
}
接着在AutoConfigurationSorter的doSortByAfterAnnotation方法里实现自动配置类的加载顺序
private void doSortByAfterAnnotation(AutoConfigurationClasses classes,
List<String> toSort, Set<String> sorted, Set<String> processing,
String current) {
if (current == null) {
current = toSort.remove(0);
}
processing.add(current);
for (String after : classes.getClassesRequestedAfter(current)) {
Assert.state(!processing.contains(after),
"AutoConfigure cycle detected between " + current + " and " + after);
if (!sorted.contains(after) && toSort.contains(after)) {
doSortByAfterAnnotation(classes, toSort, sorted, processing, after);
}
}
processing.remove(current);
sorted.add(current);
}
然后在ConditionEvaluator的shouldSkip方法里处理@ConditionalXXX条件,决定类是否能被加载
public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) {
if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
return false;
}
if (phase == null) {
if (metadata instanceof AnnotationMetadata &&
ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {
return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);
}
return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);
}
List<Condition> conditions = new ArrayList<>();
//找到所有条件
for (String[] conditionClasses : getConditionClasses(metadata)) {
for (String conditionClass : conditionClasses) {
Condition condition = getCondition(conditionClass, this.context.getClassLoader());
conditions.add(condition);
}
}
AnnotationAwareOrderComparator.sort(conditions);
for (Condition condition : conditions) {
ConfigurationPhase requiredPhase = null;
if (condition instanceof ConfigurationCondition) {
requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
}
//看条件是否匹配
if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) {
return true;
}
}
return false;
}
注意:
即便是使用@AutoConfigurationBefore/After,只是给正常等待创建的bean对应的beandefinition排序,最终可能因为种种原因,导致bean的真实加载顺序不与注解一致,比如,tomcat的初始化,可能引发健康检查的bean提前被创建,而其中这个健康检查的bean引用了一个需要特定顺序创建的bean(暂且叫specialBean)时,specialBean的顺序会被打乱,提前创建!!!