Spring注解之@Import的简单介绍
作者:blue星空
@Import可以导入以下几种种类:
普通类
实现ImportSelector接口的类
实现DeferredImportSelector接口的类
实现ImportBeanDefinitionRegistrar接口的类
普通类
被导入的类会被容器注册成一个Bean,可以被依赖注入使用。【4.2 版本之前只可以导入配置类;4.2版本之后也可以导入普通类,导入的类会被当作配置类】
@Import注册一个类时,这个配置类不应该被@Component或者@Configuration注解标记。Spring中会将所有的bean class封装成一个ConfigurationClass,并且此后会判断被封装的bean class是否是由其他类导入的.
@Configuration <strong>@Import(OtherBean.</strong><strong>class) </strong>public class SpringConfig { }
public class OtherBean { }
ImportSelector实现类
实现类不会被注册成Bean,接口方法的返回值会被注册成Bean。【BeanName是全类名】
@Configuration <strong>@Import(MyImportSelector.</strong><strong>class) </strong>public class SpringConfig { }
public class MyImportSelector implements<strong> ImportSelector</strong> { @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { return new String[]{OtherBean.class.getName()}; } }
DeferredImportSelector实现类
DeferredImportSelector是ImportSelector的子接口, 所以它们的实现方式一样,只是Spring的处理方式不同。DeferredImportSelector和SpringBoot中自动导入配置文件的延迟导入有关。
@Configuration <strong>@Import(MyDeferredImportSelector.</strong><strong>class) </strong>public class SpringConfig { }
public class MyDeferredImportSelector implements<strong> DeferredImportSelector</strong> { @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { return new String[]{OtherBean.class.getName()}; } }
ImportBeanDefinitionRegistrar实现类
实现类不会被注册为bean,但是会回调其接口方法,由开发者通过Spring api手动向Spring容器注册bean。【类似于BeanFactoryPostRegister】
@Configuration <strong>@Import(MyImportBeanDefinitionRegistrar.</strong><strong>class) </strong>public class SpringConfig { }
public class MyImportBeanDefinitionRegistrar implements<strong> ImportBeanDefinitionRegistrar</strong> { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { BeanDefinition beanDefinition = new RootBeanDefinition(); String beanName = StringUtils.uncapitalize(OtherBean.class.getSimpleName()); beanDefinition.setBeanClassName(OtherBean.class.getName()); registry.registerBeanDefinition(beanName,beanDefinition); } }
附:@Import相关源码解析
加载解析@Import
注解位于BeanFactoryPostProcessor
处理的时候:
AbstractApplicationContext
的refresh
方法
-> invokeBeanFactoryPostProcessors(beanFactory);
-> PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
-> registryProcessor.postProcessBeanDefinitionRegistry(registry);
这里的registryProcessor
,我们指ConfigurationClassPostProcessor
ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(registry)
-> processConfigBeanDefinitions(registry)
:
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { //省略一些配置检查与设置的逻辑 //根据@Order注解,排序所有的@Configuration类 configCandidates.sort((bd1, bd2) -> { int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition()); int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition()); return Integer.compare(i1, i2); }); // 创建ConfigurationClassParser解析@Configuration类 ConfigurationClassParser parser = new ConfigurationClassParser( this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry); //剩余没有解析的@Configuration类 Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates); //已经解析的@Configuration类 Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size()); do { //解析 parser.parse(candidates); parser.validate(); Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses()); configClasses.removeAll(alreadyParsed); // 生成类定义读取器读取类定义 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) { //省略检查是否有其他需要加载的配置的逻辑 } } while (!candidates.isEmpty()); //省略后续清理逻辑 }
其中parser.parse(candidates)
的逻辑主要由org.springframework.context.annotation.ConfigurationClassParser
实现,功能是加载@Import
注解还有即系@Import
注解。reader.loadBeanDefinitions(configClasses);
的逻辑主要由org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader
的loadBeanDefinitionsForConfigurationClass
方法实现,功能是将上面解析的配置转换为BeanDefinition
就是Bean
定义。
总结
到此这篇关于Spring注解之@Import的文章就介绍到这了,更多相关Spring注解@Import内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!