@Import 是一个能让类生成为 Spring Bean 的注解。
@Import 注解它主要是配合 ImportSelector 和 @ImportBeanDefinitionRegistrar 的子类,或者普通的 Java Bean 类使用。
@Import 注解源码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
/**
* 需要引入的类,通常是 @ImportSelector , @ImportBeanDefinitionRegistrar 的子类;或者是当成其他普通的 Bean 来使用。
*/
Class>[] value();
}
普通 Bean 用法
在 @Import 注解导入普通 Bean 时,这个普通 Bean 必须要有无参构造方法,不然的话会报错。
例子
@SpringBootTest
@Import(ImportNormalBeanTest.NormalBeanClass.class)
public class ImportNormalBeanTest {
@Autowired
ApplicationContext ctx;
@Test
void testNormalBean(){
NormalBeanClass bean = ctx.getBean(NormalBeanClass.class);
System.out.println(bean);
}
public static class NormalBeanClass{
@Override
public String toString() {
return "normal bean";
}
}
}
测试结果
normal bean
ImportSelector
ImportSelector 接口通过自定义的算法,去选择要引入的 Spring Bean 。如果 ImportSelector 的子类实现了以下的接口,它会按照接口的顺序先调用这些接口的方法,再去调用 ImportSelector 的方法:
- BeanClassLoaderAware
- BeanFactoryAware
- EnvironmentAware
- ResourceLoaderAware
ImportSelector 源码
public interface ImportSelector {
// 返回要加载的 class 全限定名,可以通过 Class.getName() 来获取
String[] selectImports(AnnotationMetadata importingClassMetadata);
// 是否过滤掉该 ImportSelector
// Predicate 返回 true 表示过滤掉,false 或者 null 表示不过滤
@Nullable
default Predicate getExclusionFilter() {
return null;
}
}
例子
@SpringBootTest
@Import(ImportSelectorTest.TestBeanImportSelector.class)
public class ImportSelectorTest {
@Autowired
private ApplicationContext ctx;
@Test
void test(){
final TestBeanClass bean = ctx.getBean(TestBeanClass.class);
System.out.println(bean);
}
// 自定义一个 ImportSelector , 并且实现了4个 aware 的接口,用于验证调用顺序
public static class TestBeanImportSelector implements ImportSelector,
EnvironmentAware, BeanFactoryAware, BeanClassLoaderAware, ResourceLoaderAware {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
System.out.println("invoke selectImports method");
return new String[]{TestBeanClass.class.getName()};
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("BeanClassLoader set");
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("beanFactory set");
}
@Override
public void setEnvironment(Environment environment) {
System.out.println("environment set");
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
System.out.println("resourceLoader set");
}
}
public static class TestBeanClass{
@Override
public String toString() {
return "test bean";
}
}
}
运行结果
BeanClassLoader set
beanFactory set
environment set
resourceLoader set
invoke selectImports method
test bean
配合自定义注解使用
ImportSelector 还能配合自定义注解,来决定需要引入的 Bean。
例子
/**
* 这里同时引入 TestBeanClassAnnotation 和 AnotherTestBeanClassAnnotation 这2个注解
* 那么会将 TestBeanClass 和 AnotherTestBeanClass 对应的 Bean 加到到 Spring 容器中去
* 可以只使用其中一个注解,以只加载注解关联的 Bean
*/
@SpringBootTest
@ImportSelectorTest.TestBeanClassAnnotation
@ImportSelectorTest.AnotherTestBeanClassAnnotation
public class ImportSelectorTest {
@Autowired
private ApplicationContext ctx;
@Test
void test(){
System.out.println(ctx.getBean(TestBeanClass.class));
System.out.println(ctx.getBean(AnotherTestBeanClass.class));
}
/**
* 表示只引入 TestBeanClass 的 Bean
* 并且通过 @Import 注解来引入 TestBeanImportSelector
*/
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Target(ElementType.TYPE)
@Import(ImportSelectorTest.TestBeanImportSelector.class)
public @interface TestBeanClassAnnotation{
}
/**
* 表示只引入 AnotherTestBeanClass 的 Bean
* 并且通过 @Import 注解来引入 TestBeanImportSelector
*/
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Target(ElementType.TYPE)
@Import(ImportSelectorTest.TestBeanImportSelector.class)
public @interface AnotherTestBeanClassAnnotation{
}
// 自定义一个 ImportSelector , 并且实现了4个 aware 的接口,用于验证调用顺序
public static class TestBeanImportSelector implements ImportSelector,
EnvironmentAware, BeanFactoryAware, BeanClassLoaderAware, ResourceLoaderAware {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
System.out.println("invoke selectImports method");
List classNameList = new ArrayList<>();
// 获取引用到该 ImportSelector 的注解
Set annotationTypes = importingClassMetadata.getAnnotationTypes();
for (String annotationType : annotationTypes) {
if(TestBeanClassAnnotation.class.getName().equals(annotationType)){
classNameList.add(TestBeanClass.class.getName());
}else if(AnotherTestBeanClassAnnotation.class.getName().equals(annotationType)){
classNameList.add(AnotherTestBeanClass.class.getName());
}
}
return classNameList.toArray(new String[0]);
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("BeanClassLoader set");
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("beanFactory set");
}
@Override
public void setEnvironment(Environment environment) {
System.out.println("environment set");
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
System.out.println("resourceLoader set");
}
}
// 要使用到的 Bean 对应的 class
public static class TestBeanClass{
@Override
public String toString() {
return "test bean";
}
}
public static class AnotherTestBeanClass{
@Override
public String toString(){
return "another test bean";
}
}
}
输出结果
BeanClassLoader set
beanFactory set
environment set
resourceLoader set
invoke selectImports method
test bean
another test bean
ImportBeanDefinitionRegistrar
ImportBeanDefinitionRegistrar 接口适合使用在创建 BeanDefinition 的场景,例如 Mybatis-Spring 的 MapperScannerRegistrar ,
就是实现了 ImportBeanDefinitionRegistrar 的 registerBeanDefinitions 方法,来注入 Mapper 接口对应的 BeanDefinition。
ImportBeanDefinitionRegistrar 和 ImportSelector 一样,如果 ImportBeanDefinitionRegistrar 的子类也实现了指定的 Aware 子类,也会按照以下顺序来执行:
- BeanClassLoaderAware
- BeanFactoryAware
- EnvironmentAware
- ResourceLoaderAware
ImportBeanDefinitionRegistrar 源码
public interface ImportBeanDefinitionRegistrar {
default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry,
BeanNameGenerator importBeanNameGenerator) {
registerBeanDefinitions(importingClassMetadata, registry);
}
// 利用 BeanDefinitionRegistry 来注册 BeanDefinition ,后续 Spring 容器通过 BeanDefinition 来创建 Bean
default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
}
}
例子
@SpringBootTest
@Import(ImportBeanDefinitionRegistrarTest.TestImportBeanDefinitionRegistrar.class)
public class ImportBeanDefinitionRegistrarTest {
@Autowired
private ApplicationContext ctx;
@Test
void test(){
System.out.println(ctx.getBean(TestBean.class));
}
public static class TestImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 添加 TestBean 对应的 BeanDefinition 到 BeanDefinitionRegistry 中
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(TestBean.class);
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
registry.registerBeanDefinition("testBean", beanDefinition);
}
}
public static class TestBean{
@Override
public String toString() {
return "test bean";
}
}
}
输出结果
test bean
源码解析
在 Spring 初始化容器时,会调用到 AbstractApplicationContext#refresh() 的方法:
AbstractApplicationContext#refresh() 方法
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
prepareRefresh();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
try {
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// 调用所有注册到的 BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
// 忽略后面部分的代码
}
// 忽略后面部分的代码
}
}
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// 实际上调用以下方法来调用所有 BeanFactoryPostProcessor
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// 忽略以下方法
}
从上面的源码得知,实际上调用 PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()
方法。
PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors() 方法
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {
Set processedBeans = new HashSet<>();
if (beanFactory instanceof BeanDefinitionRegistry registry) {
// 存储所有 BeanFactoryPostProcessor
List regularPostProcessors = new ArrayList<>();
// 存储所有 BeanDefinitionRegistryPostProcessor
List registryProcessors = new ArrayList<>();
//忽略中间代码
// 存储当前已经获取到的 BeanDefinitionRegistryPostProcessor
List currentRegistryProcessors = new ArrayList<>();
// 扫描 Beanfactory 已经加载到的 BeanDefinitionRegistryPostProcessor 的 bean
// 其中会扫描到一个 ConfigurationClassPostProcessor 的 Bean , 它实现了 BeanDefinitionRegistryPostProcessor 接口
// 这个 Bean 通过重写 BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry() 的方法去做处理 @Import 注解的逻辑
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 这里会调用已经获取到的 BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry() 方法,其中已经包含 ConfingurationClassPostProcssor
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
// 忽略中间代码
}
// 忽略后续代码
}
// 遍历地调用 postProcessors 参数列表的 postProcessBeanDefinitionRegistry() 方法
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup) {
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
StartupStep postProcessBeanDefRegistry = applicationStartup.start("spring.context.beandef-registry.post-process")
.tag("postProcessor", postProcessor::toString);
// 循环调用 BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry() 方法
postProcessor.postProcessBeanDefinitionRegistry(registry);
postProcessBeanDefRegistry.end();
}
}
在 PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()
中,Spring 加载了 ConfigurationClassPostProcessor 的 Bean 进去。
因为 ConfigurationClassPostProcessor 是 BeanDefinitionRegistryPostProcessor 的子类,故在 invokeBeanDefinitionRegistryPostProcessors
方法中便会调用到ConfingurationClassPostProcssor#postProcessBeanDefinitionRegistry()
的方法。
ConfingurationClassPostProcssor#postProcessBeanDefinitionRegistry() 方法
// 这里只展示核心的 postProcessBeanDefinitionRegistry() 方法
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
// 忽略上面部分的代码
// ConfigurationClassPostProcessor 实际上是调用 processConfigBeanDefinitions() 方法来做具体的逻辑
processConfigBeanDefinitions(registry);
}
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List configCandidates = new ArrayList<>();
// 从 BeanDefinitionRegistry 中获取 BeanDefinitionNames 列表
String[] candidateNames = registry.getBeanDefinitionNames();
// 添加 BeanDefinitionNames 列表到 configCandidates 类表中去
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// 如果 configCandidates 列表为空,则结束流程
if (configCandidates.isEmpty()) {
return;
}
// 如果 BeanDefinition 关联的 class 有 @Order 注解的话,就去排序
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(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// Parse each @Configuration class
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set candidates = new LinkedHashSet<>(configCandidates);
Set alreadyParsed = new HashSet<>(configCandidates.size());
do {
StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
// 解析 @Import 注解的入口,并将读取到的类添加到 parser.configurationClasses 列表中
parser.parse(candidates);
parser.validate();
// 读取 parser.configurationClasses.keySet()
Set configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
// 去掉已经加载过的 configClasses
configClasses.removeAll(alreadyParsed);
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
// 将 configClasses 转换成 BeanDefinition , 供给后面创建 Bean 的使用
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
// 忽略后续部分代码
}
while (!candidates.isEmpty());
// 忽略后续部分代码
}
ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry()
方法实际上是调用了 processConfigBeanDefinitions
方法。他主要做了这些事情:
processConfigBeanDefinitions
先去扫描BeanDefinitionRegistry
维护的BeanDefinitionNames
列表- 通过
BeanDefinitionNames
列表转换成configCandidates
列表 - 对
configCandidates
列表的元素做排序操作 - 通过
ConfigurationClassParser#parse()
方法,去读取configCandidates
列表,并将configCandidates
列表中有使用到的 @Import 注解的类,调用它们相关的方法。
例如ImportSelector#selectImports()
方法
并且将调用方法后得到的结果,存入到ConfigurationClassParser.configurationClasses
的 map 中去 - 调用
ConfigurationClassBeanDefinitionReader#loadBeanDefinitions
方法,将ConfigurationClassParser.configurationClasses
的 map 内容转换成 BeanDefinition 列表
从上面的流程中, ConfigurationClassParser#parse()
是读取 @Import
注解的关键入口。
ConfigurationClassParser#parse() 方法
public void parse(Set configCandidates) {
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
// 这里主要是调用了 parse() 方法
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());
}
}
// 忽略下面的代码
}
this.deferredImportSelectorHandler.process();
}
protected final void parse(Class> clazz, String beanName) throws IOException {
// parse() 方法调用了 processConfigurationClass() 方法
processConfigurationClass(new ConfigurationClass(clazz, beanName), DEFAULT_EXCLUSION_FILTER);
}
protected void processConfigurationClass(ConfigurationClass configClass, Predicate filter) throws IOException {
// 忽略上面部分的代码
SourceClass sourceClass = asSourceClass(configClass, filter);
do {
// 主要是调用 doProcessConfigurationClass() 方法
sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
}
while (sourceClass != null);
// 将 doProcessConfigurationClass() 方法修改的 configClass 塞到 configurationClasses 的 Map 中去
this.configurationClasses.put(configClass, configClass);
}
protected final SourceClass doProcessConfigurationClass(
ConfigurationClass configClass, SourceClass sourceClass, Predicate filter)
throws IOException {
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
// Recursively process any member (nested) classes first
processMemberClasses(configClass, sourceClass, filter);
}
// 解析 @PropertySource 的注解
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.propertySourceRegistry != null) {
this.propertySourceRegistry.processPropertySource(propertySource);
}
else {
logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
// 解析 @ComponentScan 的注解
Set 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 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), filter, 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 beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// 忽略下面的方法
}
从上面的代码执行流程中,可以看到解析 @Import 注解的是 ConfigurationClassParser#processImports()
方法
ConfigurationClassParser#processImports() 方法
该方法时解析 @Import 注解的核心逻辑:
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection importCandidates, Predicate exclusionFilter,
boolean checkForCircularImports) {
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 selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
this.environment, this.resourceLoader, this.registry);
Predicate selectorFilter = selector.getExclusionFilter();
if (selectorFilter != null) {
exclusionFilter = exclusionFilter.or(selectorFilter);
}
if (selector instanceof DeferredImportSelector) {
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
}
else {
// 调用 ImportSelector#selectImports() 方法 ,获取 Bean 对应的 class 名字
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
// 将这些获取到的 class 名字递归地调用 processImports() 方法
processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, 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 =
ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
this.environment, this.resourceLoader, this.registry);
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
// 解析其他类型,会把它们当作 @Configuration 类来处理
else {
// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
// process it as an @Configuration class
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
}
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configClass.getMetadata().getClassName() + "]: " + ex.getMessage(), ex);
}
finally {
this.importStack.pop();
}
}
}
ConfigurationClassBeanDefinitionReader#loadBeanDefinitions() 方法
当 Spring 加载完了 @Import 注解之后,会通过 ConfigurationClassBeanDefinitionReader#loadBeanDefinitions()
方法来调用 ImportBeanDefinitionRegistrar#registerBeanDefinitions()
方法。
ImportBeanDefinitionRegistrar#registerBeanDefinitions()
方法就是 ImportBeanDefinitionRegistrar
的实现类要实现的方法。
public void loadBeanDefinitions(Set configurationModel) {
TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
for (ConfigurationClass configClass : configurationModel) {
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
private void loadBeanDefinitionsForConfigurationClass(
ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
// 忽略上面的代码
// 这里就是调用 ImportBeanDefinitionRegistrars#registerBeanDefinitions() 方法的入口
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
private void loadBeanDefinitionsFromRegistrars(Map registrars) {
registrars.forEach((registrar, metadata) ->
// 调用 ImportBeanDefinitionRegistrars#registerBeanDefinitions() 方法
registrar.registerBeanDefinitions(metadata, this.registry, this.importBeanNameGenerator));
}