AutoConfigurationImportSelector#selectImports()什么时候被调用
selectImports()调用流程抛析
为了解selectImports()何时被调用,我们从程序初始化SpringApplication.run()来查看,run()会调用到this.refreshContext(context) -> AbstractApplicationContext.refreshContext()。
public ConfigurableApplicationContext run(String... args) {
long startTime = System.nanoTime();
DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
ConfigurableApplicationContext context = null;
this.configureHeadlessProperty();
SpringApplicationRunListeners listeners = this.getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
this.configureIgnoreBeanInfo(environment);
Banner printedBanner = this.printBanner(environment);
context = this.createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
this.refreshContext(context);
this.afterRefresh(context, applicationArguments);
在AbstractApplicationContext中的方法调用
AbstractApplicationContext的refresh() -> invokeBeanFactoryPostProcessors(beanFactory) -> PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors())
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
this.prepareRefresh();
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
try {
this.postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
this.invokeBeanFactoryPostProcessors(beanFactory);
this.registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
this.initMessageSource();
this.initApplicationEventMulticaster();
this.onRefresh();
this.registerListeners();
this.finishBeanFactoryInitialization(beanFactory);
this.finishRefresh();
} catch (BeansException var10) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);
}
this.destroyBeans();
this.cancelRefresh(var10);
throw var10;
} finally {
this.resetCommonCaches();
contextRefresh.end();
}
}
}
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors());
if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean("loadTimeWeaver")) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()中的代码registryProcessor.postProcessBeanDefinitionRegistry(registry);调用了BeanDefinitionRegistryPostProcessor接口的实现在这里关注ConfigurationClassPostProcessor实现类
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
Set<String> processedBeans = new HashSet();
ArrayList regularPostProcessors;
ArrayList registryProcessors;
int var9;
ArrayList currentRegistryProcessors;
String[] postProcessorNames;
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry)beanFactory;
regularPostProcessors = new ArrayList();
registryProcessors = new ArrayList();
Iterator var6 = beanFactoryPostProcessors.iterator();
while(var6.hasNext()) {
BeanFactoryPostProcessor postProcessor = (BeanFactoryPostProcessor)var6.next();
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor)postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
ConfigurationClassPostProcessor中关注parser.parse(candidates)和 this.reader.loadBeanDefinitions(configClasses),这两个方法分别用来解析和加载bean。
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
...
ConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet(configCandidates);
HashSet alreadyParsed = new HashSet(configCandidates.size());
do {
StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
parser.parse(candidates);
parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(registry, this.sourceExtractor, this.resourceLoader, this.environment, this.importBeanNameGenerator, parser.getImportRegistry());
}
this.reader.loadBeanDefinitions(configClasses);
...
ConfigurationClassPostProcessor#parser.parse(candidates)中调用了
parse(AnnotationMetadata metadata, String beanName) ->
processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) -> doProcessConfigurationClass(configClass, sourceClass, filter) ->
this.processImports(configClass, sourceClass, this.getImports(sourceClass), filter, true) -> this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector)selector)
public void parse(Set<BeanDefinitionHolder> configCandidates) {
Iterator var2 = configCandidates.iterator();
while(var2.hasNext()) {
BeanDefinitionHolder holder = (BeanDefinitionHolder)var2.next();
BeanDefinition bd = holder.getBeanDefinition();
try {
if (bd instanceof AnnotatedBeanDefinition) {
this.parse(((AnnotatedBeanDefinition)bd).getMetadata(), holder.getBeanName());
} else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition)bd).hasBeanClass()) {
this.parse(((AbstractBeanDefinition)bd).getBeanClass(), holder.getBeanName());
} else {
this.parse(bd.getBeanClassName(), holder.getBeanName());
}
} catch (BeanDefinitionStoreException var6) {
throw var6;
} catch (Throwable var7) {
throw new BeanDefinitionStoreException("Failed to parse configuration class [" + bd.getBeanClassName() + "]", var7);
}
}
this.deferredImportSelectorHandler.process();
}
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
this.processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
}
protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
if (!this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
ConfigurationClass existingClass = (ConfigurationClass)this.configurationClasses.get(configClass);
if (existingClass != null) {
if (configClass.isImported()) {
if (existingClass.isImported()) {
existingClass.mergeImportedBy(configClass);
}
return;
}
this.configurationClasses.remove(configClass);
this.knownSuperclasses.values().removeIf(configClass::equals);
}
ConfigurationClassParser.SourceClass sourceClass = this.asSourceClass(configClass, filter);
do {
sourceClass = this.doProcessConfigurationClass(configClass, sourceClass, filter);
} while(sourceClass != null);
this.configurationClasses.put(configClass, configClass);
}
}
private void processImports(ConfigurationClass configClass, ConfigurationClassParser.SourceClass currentSourceClass, Collection<ConfigurationClassParser.SourceClass> importCandidates, Predicate<String> exclusionFilter, boolean checkForCircularImports) {
if (!importCandidates.isEmpty()) {
if (checkForCircularImports && this.isChainedImportOnStack(configClass)) {
this.problemReporter.error(new ConfigurationClassParser.CircularImportProblem(configClass, this.importStack));
} else {
this.importStack.push(configClass);
try {
Iterator var6 = importCandidates.iterator();
while(var6.hasNext()) {
ConfigurationClassParser.SourceClass candidate = (ConfigurationClassParser.SourceClass)var6.next();
Class candidateClass;
if (candidate.isAssignable(ImportSelector.class)) {
candidateClass = candidate.loadClass();
ImportSelector selector = (ImportSelector)ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class, this.environment, this.resourceLoader, this.registry);
Predicate<String> selectorFilter = selector.getExclusionFilter();
if (selectorFilter != null) {
exclusionFilter = exclusionFilter.or(selectorFilter);
}
if (selector instanceof DeferredImportSelector) {
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector)selector);
} else {
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<ConfigurationClassParser.SourceClass> importSourceClasses = this.asSourceClasses(importClassNames, exclusionFilter);
this.processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
}
} else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
candidateClass = candidate.loadClass();
ImportBeanDefinitionRegistrar registrar = (ImportBeanDefinitionRegistrar)ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class, this.environment, this.resourceLoader, this.registry);
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
} else {
this.importStack.registerImport(currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
this.processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
}
}
} catch (BeanDefinitionStoreException var17) {
throw var17;
} catch (Throwable var18) {
throw new BeanDefinitionStoreException("Failed to process import candidates for configuration class [" + configClass.getMetadata().getClassName() + "]", var18);
} finally {
this.importStack.pop();
}
}
}
}
内部类DeferredImportSelectorHandler将属于DeferredImportSelector的实例放构造成了 DeferredImportSelectorHolder对象并且放入到集合中,然后在process()中调用DeferredImportSelectorGroupingHandler#register()中处理这些实例。(我在这里遇到一个问题,就是process方法是什么时候被调用的在代码中没有找到还需要再了解)
private class DeferredImportSelectorHandler {
@Nullable
private List<ConfigurationClassParser.DeferredImportSelectorHolder> deferredImportSelectors;
private DeferredImportSelectorHandler() {
this.deferredImportSelectors = new ArrayList();
}
public void handle(ConfigurationClass configClass, DeferredImportSelector importSelector) {
ConfigurationClassParser.DeferredImportSelectorHolder holder = new ConfigurationClassParser.DeferredImportSelectorHolder(configClass, importSelector);
if (this.deferredImportSelectors == null) {
ConfigurationClassParser.DeferredImportSelectorGroupingHandler handler = ConfigurationClassParser.this.new DeferredImportSelectorGroupingHandler();
handler.register(holder);
handler.processGroupImports();
} else {
this.deferredImportSelectors.add(holder);
}
}
public void process() {
List<ConfigurationClassParser.DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
this.deferredImportSelectors = null;
try {
if (deferredImports != null) {
ConfigurationClassParser.DeferredImportSelectorGroupingHandler handler = ConfigurationClassParser.this.new DeferredImportSelectorGroupingHandler();
deferredImports.sort(ConfigurationClassParser.DEFERRED_IMPORT_COMPARATOR);
deferredImports.forEach(handler::register);
handler.processGroupImports();
}
} finally {
this.deferredImportSelectors = new ArrayList();
}
}
}
DeferredImportSelectorGroupingHandler类,在register中将deferredImport放入到configurationClasses的Map中。还记得在之前提到的ConfigurationClassPostProcessor中关注parser.parse(candidates)和 this.reader.loadBeanDefinitions(configClasses)方法吗?这里parse方法处理完获取到了configClasses接下来就由loadBeanDefinitions(configClasses)对进行Bean的加载。
public void register(ConfigurationClassParser.DeferredImportSelectorHolder deferredImport) {
Class<? extends Group> group = deferredImport.getImportSelector().getImportGroup();
ConfigurationClassParser.DeferredImportSelectorGrouping grouping = (ConfigurationClassParser.DeferredImportSelectorGrouping)this.groupings.computeIfAbsent(group != null ? group : deferredImport, (key) -> {
return new ConfigurationClassParser.DeferredImportSelectorGrouping(this.createGroup(group));
});
grouping.add(deferredImport);
this.configurationClasses.put(deferredImport.getConfigurationClass().getMetadata(), deferredImport.getConfigurationClass());
}
在回来看ConfigurationClassPostProcessor的processConfigBeanDefinitions(BeanDefinitionRegistry registry)方法,调用 parser.parse(candidates)方法获取到configClasses,然后调用ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(configClasses)加载Bean。
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
...
StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
parser.parse(candidates);
parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(registry, this.sourceExtractor, this.resourceLoader, this.environment, this.importBeanNameGenerator, parser.getImportRegistry());
}
this.reader.loadBeanDefinitions(configClasses);
...
}
ConfigurationClassBeanDefinitionReader类中通过调用该方法创建Bean。
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
ConfigurationClassBeanDefinitionReader.TrackedConditionEvaluator trackedConditionEvaluator = new ConfigurationClassBeanDefinitionReader.TrackedConditionEvaluator();
Iterator var3 = configurationModel.iterator();
while(var3.hasNext()) {
ConfigurationClass configClass = (ConfigurationClass)var3.next();
this.loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, ConfigurationClassBeanDefinitionReader.TrackedConditionEvaluator trackedConditionEvaluator) {
if (trackedConditionEvaluator.shouldSkip(configClass)) {
String beanName = configClass.getBeanName();
if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
this.registry.removeBeanDefinition(beanName);
}
this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
} else {
if (configClass.isImported()) {
this.registerBeanDefinitionForImportedConfigurationClass(configClass);
}
Iterator var3 = configClass.getBeanMethods().iterator();
while(var3.hasNext()) {
BeanMethod beanMethod = (BeanMethod)var3.next();
this.loadBeanDefinitionsForBeanMethod(beanMethod);
}
this.loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
this.loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
}
总结
- 通过读取流程已经了解到SpringApplication.run的初始化过程会调用 importSelector();
- 内部类DeferredImportSelectorHandler的process()调用时间还需要在了解(process方法是什么时候被调用的在代码中没有找到还需要再了解);