文章目录
本文源码基于spring-context-5.3.36 版本
基本用法
@Import注解的作用简单来说就是导入一组Class到Spring的Bean容器
- 直接填class数组方式
@Import注解填入要导入的类的Class即可
@Import({
A.class , B.class... })
@Configuration
public class TestDemo {
}
- ImportSelector方式
实现ImportSelector接口,selectImport返回需要导入的类的全限定名称
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
return new String[0];
}
}
然后@Import中指定ImportSelector的实现类的Class
- ImportBeanDefinitionRegistrar方式
实现ImportBeanDefinitionRegistrar接口
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
// 通过 BeanDefinitionRegistry 构造 BeanDefinition 并进行注册
}
}
然后@Import中指定ImportBeanDefinitionRegistrar的实现类的Class
总结
- 以上三种用法方式皆可混合在一个@Import中使用,注意第一种和第二种都是以全类名的方式注册,而第三中可自定义名称
- 第一种最简单,第二种较简单,第三种需要操作BeanDefinition,较为复杂
- @Import注解不一定非要和@Configuration搭配使用,也可以和@Component等注解使用,效果一样
@Import({
A.class , B.class... })
@Component
public class TestDemo {
}
源码分析
入口
BeanDefinitionRegistryPostProcessor执行阶段生效
例如 ConfigurationClassPostProcessor
ConfigurationClassPostProcessor
ConfigurationClass
代表定义的@Configuration修饰的类,包含一些bean方法。配置加载都有一个解析过程,对ConfigurationClass的解析就是由ConfigurationClassParser#parse
方法完成的,它会解析每个配置类上的配置,包括@Import注解这个配置
public void parse(Set<BeanDefinitionHolder> configCandidates) {
// 拿到所有的BeanDefinition
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
// 根据BeanDefinition的不同实现调用不同的解析方法
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) {
.