@Import注解 -【Spring底层原理】

public class Person {

}

// 配置类

@Configuration

@Import({User.class, MyImportSelector.class})     //使用@Import导入组件,ID默认是组件的全类名

public class AppConfig {

}

ImportSelector实现类中获取要导入到容器的组件全类名,这里将ImportSelector实现类在配置类中使用@Import注解进行配置,运行启动类,可以看到容器中有Person对象:

image-20210227151242060

image-20210227151242060

【3】导入ImportBeanDefinitionRegistrar的实现类

导入ImportBeanDefinitionRegistrar的实现类需要实现ImportBeanDefinitionRegistrar类,通过实现registerBeanDefinitions方法手动注册Bean到容器中,添加修改如下代码:

// ImportBeanDefinitionRegistrar实现类

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {

// 指定Bean的名称

RootBeanDefinition beanDefinition = new RootBeanDefinition(Animal.class);

beanDefinitionRegistry.registerBeanDefinition(“Animal”, beanDefinition);

}

}

// 待注入的Animal

public class Animal {

}

// 配置类

@Configuration

@Import({User.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})     //使用@Import导入组件,ID默认是组件的全类名

public class AppConfig {

}

通过ImportBeanDefinitionRegistrar的实现类进行手动注册添加Bean,并在配置类中使用@Import注解进行配置,运行启动类,可以看到容器中有Animal对象:

image-20210227153057676

image-20210227153057676

三、源码追踪

参考:https://blog.csdn.net/mamamalululu00000000/article/details/86711079

通过@Configuration注解,会进入到doProcessConfigurationClass方法,此时解析的是appConfigure,在doProcessConfigurationClass方法里面,有个执行@Import注解的方法,即processImports

this.processImports(configClass, sourceClass, this.getImports(sourceClass), filter, true);

@Import注解执行的时机,解析配置类的时候,由ConfigurationClassParser当中的processImports来处理,在分析processImports方法之前,咱们先来看看参数getImports方法:

【1】getImports方法

进入源码查看方法,这个方法就是获取所有的@import 里面的类,流程如下:

  1. 定义一个 visited 的集合,用作 是否已经 判断过的标志

  2. 这里就是获取sourceClass 上面的 所有的 annotation,并挨个判断, 如果不是 @import ,那就 进一步递归 调用 对应的 annotation,直到全部结束

  3. 加载sourceClass 里面 的@Import annotation 里面对应的类名 ,最后返回

// 获取所有的@import 里面的类

private Set<ConfigurationClassParser.SourceClass> getImports(ConfigurationClassParser.SourceClass sourceClass) throws IOException {

Set<ConfigurationClassParser.SourceClass> imports = new LinkedHashSet();

Set<ConfigurationClassParser.SourceClass> visited = new LinkedHashSet();

this.collectImports(sourceClass, imports, visited);

return imports;

}

// 这里就是获取sourceClass 上面的 所有的 annotation, 如果不是 @import ,那就 进一步递归 调用 对应的 annotation,直到全部结束

private void collectImports(ConfigurationClassParser.SourceClass sourceClass, Set<ConfigurationClassParser.SourceClass> imports, Set<ConfigurationClassParser.SourceClass> visited) throws IOException {

if (visited.add(sourceClass)) {

Iterator var4 = sourceClass.getAnnotations().iterator();

while(var4.hasNext()) {

ConfigurationClassParser.SourceClass annotation = (ConfigurationClassParser.SourceClass)var4.next();

String annName = annotation.getMetadata().getClassName();

if (!annName.equals(Import.class.getName())) {

this.collectImports(annotation, imports, visited);

}

}

imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), “value”));

}

}

【2】processImports 方法

获取到@Import里面的类后,再来执行processImports方法,进入源码进行查看:

private void processImports(ConfigurationClass configClass, ConfigurationClassParser.SourceClass currentSourceClass, Collection<ConfigurationClassParser.SourceClass> importCandidates, Predicate exclusionFilter, boolean checkForCircularImports) {

// 准备注入的候选类集合为空 直接返回

if (!importCandidates.isEmpty()) {

// 循环注入的检查

if (checkForCircularImports && this.isChainedImportOnStack(configClass)) {

this.problemReporter.error(new ConfigurationClassParser.CircularImportProblem(configClass, this.importStack));

} else {

// 当前configClass加入到ImportStack里面

this.importStack.push(configClass);

try {

Iterator var6 = importCandidates.iterator();

// 遍历注入的候选集合

while(var6.hasNext()) {

ConfigurationClassParser.SourceClass candidate = (ConfigurationClassParser.SourceClass)var6.next();

Class candidateClass;

// 如果是实现了ImportSelector接口的类

if (candidate.isAssignable(ImportSelector.class)) {

candidateClass = candidate.loadClass();

ImportSelector selector = (ImportSelector)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 {

// 调用selector当中的selectImports方法,得到要注入的类的全限定名

String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());

Collection<ConfigurationClassParser.SourceClass> importSourceClasses = this.asSourceClasses(importClassNames, exclusionFilter);

this.processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);

}

// 如果是ImportBeanDefinitionRegistrar 则configClass.addImportBeanDefinitionRegistrar 提前放到一个map当中

} 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);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值