简介
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation;
import org.springframework.core.type.AnnotationMetadata;
/**
* Interface to be implemented by types that determine which @{@link Configuration}
* class(es) should be imported based on a given selection criteria, usually one or
* more annotation attributes.
*
* <p>An {@link ImportSelector} may implement any of the following
* {@link org.springframework.beans.factory.Aware Aware} interfaces,
* and their respective methods will be called prior to {@link #selectImports}:
* <ul>
* <li>{@link org.springframework.context.EnvironmentAware EnvironmentAware}</li>
* <li>{@link org.springframework.beans.factory.BeanFactoryAware BeanFactoryAware}</li>
* <li>{@link org.springframework.beans.factory.BeanClassLoaderAware BeanClassLoaderAware}</li>
* <li>{@link org.springframework.context.ResourceLoaderAware ResourceLoaderAware}</li>
* </ul>
*
* <p>{@code ImportSelector} implementations are usually processed in the same way
* as regular {@code @Import} annotations, however, it is also possible to defer
* selection of imports until all {@code @Configuration} classes have been processed
* (see {@link DeferredImportSelector} for details).
*
* @author Chris Beams
* @since 3.1
* @see DeferredImportSelector
* @see Import
* @see ImportBeanDefinitionRegistrar
* @see Configuration
*/
public interface ImportSelector {
/**
* Select and return the names of which class(es) should be imported based on
* the {@link AnnotationMetadata} of the importing @{@link Configuration} class.
*/
String[] selectImports(AnnotationMetadata importingClassMetadata);
}
从官方介绍来看,其作用是用于导入外部的配置类。如果该接口的实现类同时实现EnvironmentAware, BeanFactoryAware ,BeanClassLoaderAware或者ResourceLoaderAware,那么在调用其 selectImports 方法之前会先调用上述接口中对应的方法,如果需要在所有的@Configuration处理完再导入,则可以实现 DeferredImportSelector 接口。
很多三方框架集成Spring 的时候,都会通过实现该接口,配合@Import注解来使自己的配置类生效。还有一些Spring自身的@Enable* 注解,比如@EnableTransactionManagement
,根据注解上的属性来选择一个配置类生效。当然,除了导入配置类外,也是可以导入普通的类,来作为bean注册到容器中的。
使用方式
自定义一个 ImportSelector 实现类
public class TeacherImport implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
// 这里就导入一个普通的bean到容器中
return new String[]{Teacher.class.getName()};
}
}
public class Teacher {
}
定义一个配置类,使用@Import 注解导入该类
@Import(TeacherImport.class)
public class Config {
}
最后在main方法中创建一个容器加载该配置类并获取Teacher
public class Main {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config.class);
System.out.println(applicationContext.getBean(Teacher.class));
}
}
运行后是可以获取到该bean,说明 TeacherImport
已经生效了。
执行时机
分析下 ImportBeanDefinitionRegistrar 接口是如何起作用的。
在Spring IOC 源码解析之refresh(二)源码解析的“invokeBeanFactoryPostProcessors”一节中讲到ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法会进行注解扫描,处理@Configuration/@Component等注解,扫描、注册包下的类,处理@Import/@ImportResource/@Bean 注解等,所以就从ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法开始分析。
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
// 获取所有的bean定义名称
String[] candidateNames = registry.getBeanDefinitionNames();
// 遍历每个bean定义
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
// 判断bean定义的configurationClass属性,如果是full或lite,说明已经作为配置类处理过了
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
// 判断是否是配置类,即类上是否有注解@Configuration,@Component,@ComponentScan,
// @Import,@ImportResource,或方法上有@Bean注解
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
// 是配置类则加入到configCandidates
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// 没有找到配置类则立即返回
if (configCandidates.isEmpty()) {
return;
}
// Sort by previously determined @Order value, if applicable
// 排序
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
// Detect any custom bean name generation strategy supplied through the enclosing application context
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// 配置类解析器
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
// 候选配置类的bean定义
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
// 存放已经解析过的配置类
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
// 解析配置类
parser.parse(candidates);
parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
candidates.clear();
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
Set<String> alreadyParsedClasses = new HashSet<>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
// Clear cache in externally provided MetadataReaderFactory; this is a no-op
// for a shared cache since it'll be cleared by the ApplicationContext.
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
这里会将@Import注解标注的类挑选出来,主要看解析器如何解析
public void parse(Set<BeanDefinitionHolder> configCandidates) {
// 遍历每个配置类,分别进行解析
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
if (bd instanceof AnnotatedBeanDefinition) {
// 注解方式走这里
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
}
else {
parse(bd.getBeanClassName(), holder.getBeanName());
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
}
}
this.deferredImportSelectorHandler.process();
}
// metadata是配置类上的所有注解信息。将注解元信息和beanName封装为ConfigurationClass,
// 每个配置类都对应一个ConfigurationClass
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
processConfigurationClass(new ConfigurationClass(metadata, beanName));
}
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
// 根据@Conditional注解确定是否应跳过
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
if (existingClass != null) {
if (configClass.isImported()) {
if (existingClass.isImported()) {
existingClass.mergeImportedBy(configClass);
}
// Otherwise ignore new imported config class; existing non-imported class overrides it.
return;
}
else {
// Explicit bean definition found, probably replacing an import.
// Let's remove the old one and go with the new one.
this.configurationClasses.remove(configClass);
this.knownSuperclasses.values().removeIf(configClass::equals);
}
}
// 递归处理配置类及其父类
// configClass表示这个配置类,sourceClass表示当前解析的类(配置类和它的父类)
SourceClass sourceClass = asSourceClass(configClass);
do {
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
}
while (sourceClass != null);
// 将该配置类存放到configurationClasses缓存中,表明处理完了
this.configurationClasses.put(configClass, configClass);
}
@Nullable
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
// Recursively process any member (nested) classes first
processMemberClasses(configClass, sourceClass);
}
// 处理 @PropertySource 注解
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
else {
logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
// 处理 @ComponentScan 注解
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// Check the set of scanned definitions for any further config classes and parse recursively if needed
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
// 处理 @Import 注解
processImports(configClass, sourceClass, getImports(sourceClass), true);
// 处理 @ImportResource 注解
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
String[] resources = importResource.getStringArray("locations");
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}
// 处理 @Bean 注解标注的方法
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// 处理接口的默认方法
processInterfaces(configClass, sourceClass);
// 处理父类
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (superclass != null && !superclass.startsWith("java") &&
!this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
// Superclass found, return its annotation metadata and recurse
return sourceClass.getSuperClass();
}
}
// 没有父类,则表明该配置类都递归解析完了
return null;
}
这里我们就只看如何处理 @Import 注解
首先通过getImports方法获取类上 @Import 要导入的值
private Set<SourceClass> getImports(SourceClass sourceClass) throws IOException {
Set<SourceClass> imports = new LinkedHashSet<>();
Set<SourceClass> visited = new LinkedHashSet<>();
collectImports(sourceClass, imports, visited);
return imports;
}
private void collectImports(SourceClass sourceClass, Set<SourceClass> imports, Set<SourceClass> visited)
throws IOException {
// 将sourceClass加入到visited中,表示该类解析过了,
// 如果递归时遇到相同的注解,即跳过(注解也可以被别的注解标注)
if (visited.add(sourceClass)) {
// 遍历类上的所有注解
for (SourceClass annotation : sourceClass.getAnnotations()) {
String annName = annotation.getMetadata().getClassName();
// 如果注解不是@Import,就递归该注解上的注解,
// 如果也有@Import,也要一起获取
if (!annName.equals(Import.class.getName())) {
collectImports(annotation, imports, visited);
}
}
// 将 @Import 中要导入的类放入imports中
imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));
}
}
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, boolean checkForCircularImports) {
// 如果没有@Import则直接返回
if (importCandidates.isEmpty()) {
return;
}
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
// 将配置类压入栈
this.importStack.push(configClass);
try {
// 遍历要导入的类
for (SourceClass candidate : importCandidates) {
// 导入的是ImportSelector实现类
if (candidate.isAssignable(ImportSelector.class)) {
// Candidate class is an ImportSelector -> delegate to it to determine imports
Class<?> candidateClass = candidate.loadClass();
// 实例化ImportSelector
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
// 调用Aware相关方法
ParserStrategyUtils.invokeAwareMethods(
selector, this.environment, this.resourceLoader, this.registry);
// 实现了 DeferredImportSelector 时的处理
if (selector instanceof DeferredImportSelector) {
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
}
else {
// 调用selectImports方法,获取到要导入的字符串数组
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
// 递归调用,相当于将importClassNames也当做@Import里的值,
// 因为这些类也可能实现这两个接口。
// 当然如果是普通的一个类,这次调用后就会执行下面else中的逻辑了
processImports(configClass, currentSourceClass, importSourceClasses, false);
}
}
// 导入的是ImportBeanDefinitionRegistrar实现类
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
// Candidate class is an ImportBeanDefinitionRegistrar ->
// delegate to it to register additional bean definitions
Class<?> candidateClass = candidate.loadClass();
ImportBeanDefinitionRegistrar registrar =
BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
ParserStrategyUtils.invokeAwareMethods(
registrar, this.environment, this.resourceLoader, this.registry);
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
else {
// 既不是ImportSelector实现类也不是ImportBeanDefinitionRegistrar实现类,
// 则将它作为配置类,由配置类解析器重新解析上面的注解。
// 特别说明,这种情况下,也会将该类作为bean注册到容器中,
// 上面两种的导入类本身并不会被注册进容器中
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
processConfigurationClass(candidate.asConfigClass(configClass));
}
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configClass.getMetadata().getClassName() + "]", ex);
}
finally {
// 处理完后出栈
this.importStack.pop();
}
}
}
这里我们的例子是返回Teacher类,所以最终会进入else逻辑中。
processConfigurationClass(candidate.asConfigClass(configClass));
这里会将candidate转化为一个配置类,并且被当做是由configClass导入,注意这个参数是关键,正是有这个参数,candidate才会被当做bean注册到容器中。
public ConfigurationClass asConfigClass(ConfigurationClass importedBy) {
if (this.source instanceof Class) {
return new ConfigurationClass((Class<?>) this.source, importedBy);
}
return new ConfigurationClass((MetadataReader) this.source, importedBy);
}
public ConfigurationClass(MetadataReader metadataReader, @Nullable ConfigurationClass importedBy) {
this.metadata = metadataReader.getAnnotationMetadata();
this.resource = metadataReader.getResource();
this.importedBy.add(importedBy);
}
注意这里importedBy这个集合中有值了。
然后又调用processConfigurationClass方法来处理这个转化后的配置类,这样又回到了最前面,完全当做一个新的配置类来处理。这里是Teacher类,里面没有其它注解可以处理了,所以下面没有其它处理,退出当前这个递归。当然如果这个类确实是一个配置类,比如里面有@Bean注解的方法,则会继续处理。
这里需要特别说明下,如果@Import 中的 value 对应的类没有实现 ImportSelector 或 ImportBeanDefinitionRegistrar 接口,则该类会被作为bean注册进容器中,如果实现了,则不会。所以可以通过Import一个普通的类直接作为bean注册进容器。
每个配置类都这样处理,然后将处理完的配置类configClass都缓存到配置了解析器ConfigurationClassParser里。
由于上面Teacher也被当做配置类了,所以最终缓存里有两个配置类,一个是Config,一个是Teacher。
回到ConfigurationClassPostProcessor中配置类解析器解析的地方
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
// 获取所有的配置类。。。
// 配置类解析器
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
// 候选配置类的bean定义
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
// 存放已经解析过的配置类
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
// 解析配置类
parser.parse(candidates);
// 对配置类进行校验
parser.validate();
// 从解析器中获取解析完的配置类(这里有两个,Config和Teacher),
// 并移除alreadyParsed中的配置类
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// 创建一个reader来加载bean定义
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
// 加载bean定义
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
candidates.clear();
// 由于注册的自定义bean定义可能也是一个配置类,可能也被@Import 注解标注,
// 所以需要重新筛查比对下,如果是就需要循环对该类进行解析
// (由于ImportSelector在调完方法后就直接递归再调用解析,所以这里应该不会出现还没解析的配置类,
// 如果是ImportBeanDefinitionRegistrar,那可能会)
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
Set<String> alreadyParsedClasses = new HashSet<>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
// 检查新注册的类是否是配置类,如果是配置类并且还没解析过,
// 就添加到candidates候选中,这样再重新循环一遍
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
// 将导入类注册表 注册为bean
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
// Clear cache in externally provided MetadataReaderFactory; this is a no-op
// for a shared cache since it'll be cleared by the ApplicationContext.
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
这里新建了一个ConfigurationClassBeanDefinitionReader来处理,这里配置类有两个
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
// 遍历每个配置类
for (ConfigurationClass configClass : configurationModel) {
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
private void loadBeanDefinitionsForConfigurationClass(
ConfigurationClass configClass, 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());
return;
}
// 这里会注册导入的bean
if (configClass.isImported()) {
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
// 这个应该是@ImportResource的
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
// 这里是调ImportBeanDefinitionRegistrar实例方法的
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
这里configClass.isImported()就是判断上面说到的importedBy集合有没有值,由于Teacher配置类创建的时候传了这个值,所以Teacher配置类会进入该if。如果是@Import 一个普通类,也是作为配置类进入到这个if里去注册bean定义。
private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
// 配置类的元数据
AnnotationMetadata metadata = configClass.getMetadata();
// 根据配置类的元数据创建配置类的BeanDefinition
AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);
ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
configBeanDef.setScope(scopeMetadata.getScopeName());
// 这里bean名称是 包名.类名
String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
// 看该类上是否有@Lazy,@Primary,@DependsOn,@Role,@Description注解等,
// 有的话要给bean定义相关属性设置
AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata);
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 注册BeanDefinition
this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
configClass.setBeanName(configBeanName);
if (logger.isTraceEnabled()) {
logger.trace("Registered bean definition for imported class '" + configBeanName + "'");
}
}
最终注册该配置类的BeanDefinition,所以从容器中获取Teacher类型的bean时才会获取到。