Spring注解之@Import的简单介绍
blue星空 人气:0@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
定义。
总结
加载全部内容