1.@Import介绍
@Import就是用来向容器中导入bean的,可以导入标注了@ Configuration的类, 实现了ImportSelector接口、ImportBeanDefinitionRegistrar接口的类 ,也可以用于一个普通类的导入。被@Import的类是被加载到了Spring容器当中,因此无论是类本身还是类里面用@Bean注解定义的bean都可以被放入IOC容器中进行管理。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
/**
* {@link Configuration @Configuration}, {@link ImportSelector},
* {@link ImportBeanDefinitionRegistrar}, or regular component classes to import.
*/
Class<?>[] value();
}
-
@Target表明了它能作用的范围,可以作用于类、接口、枚举类
-
属性仅有一个value,表示的是一个类对象数组。例如value = {xx.class,yy.class},表示要将xx和yy交给Spring容器管理。
2.导入的类大体可以分成三大类
实现了ImportSelector接口的类
1 public interface ImportSelector {
2
3 // 返回一个包含了类全限定名的数组,这些类会注入到Spring容器当中
4 String[] selectImports(AnnotationMetadata importingClassMetadata);
5
6 // 返回一个包含了类全限定名的数组,这些类会注入到Spring容器当中
7 @Nullable
8 default Predicate<String> getExclusionFilter() {
9 return null;
10 }
11
12 }
实现了ImportBeanDefinitionRegistrar接口的类
1 public interface ImportBeanDefinitionRegistrar {
2
3 // 注册Bean定义
4 default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry,
5 BeanNameGenerator importBeanNameGenerator) {
6
7 registerBeanDefinitions(importingClassMetadata, registry);
8 }
9
10 // 注册Bean定义
11 default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
12 }
13
14 }
1 public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
2
3 @Override
4 public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
5 BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(Person.class);
6 AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
7 registry.registerBeanDefinition("person", beanDefinition);
8 }
9
10 //或者 使用如下的方法也可以,自动生成beanName
11 @Override
12 public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {
13 BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(Person.class);
14 AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
15 String beanName = importBeanNameGenerator.generateBeanName(beanDefinition, registry);
16 registry.registerBeanDefinition(beanName, beanDefinition);
17 }
18 }
3.配置类
4.普通类
3.源码分析:
private void processImports(ConfigurationClass configClass, ConfigurationClassParser.SourceClass currentSourceClass, Collection<ConfigurationClassParser.SourceClass> importCandidates, Predicate<String> exclusionFilter, boolean checkForCircularImports) {
//这个方法内部相当相当复杂,importCandidates是Import的内容,调用这个方法的时候,已经说过可能有三种情况
//这里再说下,1.Import普通类,2.Import ImportSelector,3.Import ImportBeanDefinitionRegistrar
//如果不是的话,调用selectImports方法,获得全限定类名数组,在转换成类的数组,然后再调用processImports,又特么的是一个递归调用...(这里就是spring在处理从selectImports方法中返回的全类名了,准备将它们作为配置类进行处理,也就是说如果string[]中返回的是普通类,又会调用processConfigurationClass,在调用它的过程中,就将其注册到工厂中了)
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;
//如果Import ImportSelector就跑到了第一个if中来
if (candidate.isAssignable(ImportSelector.class)) {
candidateClass = candidate.loadClass();
// 将导入的类进行实例化,实例化之后还会调用invokeAwareMethods方法,判断它是否实现了XxxAware接口,如果实现了,给其设置相应的组件
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);
}
// 判断selector是不是延迟导入类型的Selector,DeferredImportSelector扩展了ImportSelector,实现了此接口,不会在此处直接调用selector的selectImports()方法,而是会将其交给deferredImportSelectorHandler处理器后续处理,我们可以看一下这个处理器中做了什么?
// 见下面↓↓↓
if (selector instanceof DeferredImportSelector) {
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector)selector);
} else {
// 如果不是DeferredImportSelector类型的,就直接调用它的selectImports方法,获取要注册的类的全类名数组
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
//将获取到的想要注册到容器中的类名全部都解析成SourceClass对象(包含Class对象和注解元数据信息),放入集合中返回
Collection<ConfigurationClassParser.SourceClass> importSourceClasses = this.asSourceClasses(importClassNames, exclusionFilter);
// 再调用processImports()递归处理,也就是将他们当作Import({xxx.class})导入的xxx.class类来处理
this.processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
}
} else if
//如果Import ImportBeanDefinitionRegistrar就跑到了第二个if
(candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
candidateClass = candidate.loadClass();
// 实例化registrar注册器对象,在实例化后还是会调用Aware接口方法
ImportBeanDefinitionRegistrar registrar = (ImportBeanDefinitionRegistrar)ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class, this.environment, this.resourceLoader, this.registry);
// 会把数据放到ConfigurationClass中的Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> importBeanDefinitionRegistrars中去,注意此处还没有调用registrar的registerBeanDefinitions方法
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
} else {
//如果是普通类,会进到else,或者说只是没有实现ImportSelector和ImportBeanDefinitionRegistrar接口的类,因为我们通过调用selectImports()方法,获得的String[]中的类以及因为实现了DeferredImportSelector接口延迟调用了selectImports()方法获得的自动配置类(228个)-->springboot,如果没有实现上述两个接口,也会来到这里调用processConfigurationClass方法,将其当作配置类处理。
//这个方法是不是很熟悉,没错,processImports这个方法就是在processConfigurationClass方法中被调用的
//processImports又主动调用processConfigurationClass方法,是一个递归调用,因为Import的普通类,也有可能被加了@ImportResource、@ComponentScan注解 或者其他注解,所以普通类需要再次被解析
//将进入到else中的类名以及其注解元信息放入ImportStack的MultiValueMap<String, AnnotationMetadata> imports属性map中
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();
}
}
}
}
public void handle(ConfigurationClass configClass, DeferredImportSelector importSelector) {
// 将实例化好的selector以及当前解析的配置类信息封装成了DeferredImportSelectorHolder
ConfigurationClassParser.DeferredImportSelectorHolder holder = new ConfigurationClassParser.DeferredImportSelectorHolder(configClass, importSelector);
// deferredImportSelectors 默认不为null,在创建ConfigurationClassParser解析器对象时,就初始化new了DeferredImportSelectorGroupingHandler对象,而在DeferredImportSelectorGroupingHandler的空参构造器中,就给该属性deferredImportSelectors创建了对象,它是ConfigurationClassParser.DeferredImportSelectorHolder类型的ArrayList
if (this.deferredImportSelectors == null) {
ConfigurationClassParser.DeferredImportSelectorGroupingHandler handler = ConfigurationClassParser.this.new DeferredImportSelectorGroupingHandler();
handler.register(holder);
handler.processGroupImports();
} else {
// 将当前的selector的持有者保存到list集合中,后续进行处理,这就体现了延迟(Deferred)
this.deferredImportSelectors.add(holder);
}
}
如有问题欢迎指正.....