简单的说,就是在spring应用启动过程,一些被@import注解的类(这些类都实现了importBeanDefinitionRegistrar接口)会执行importBeanDefinitionRegistrar的registerBeanDefinitions方法,然后生成BeanDefinition对象,并最终注册到BeanDefinitionRegistry中,为后续实例化bean做准备的。
在哪里用到了?以我们非常熟悉的spring boot应用为例,启动类就包含了,
@SpringBootApplication注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@documented
@Inherited
@AutoConfigurationPackage
@import(AutoConfigurationimportSelector.class)
public @interface EnableAutoConfiguration {
其中@import(AutoConfigurationimportSelector.class)就是。
另外还有spring集成mybatis的注解**@MapperScan**一样也用到。
使用过程解析进入org.springframework.context.annotation.ConfigurationClassParser#doProcessConfigurationClass
// Process any @import annotations processimports(configClass, sourceClass, getimports(sourceClass), true);
进去getimports方法
private void collectimports(SourceClass sourceClass, Setimports, Set visited) throws IOException { if (visited.add(sourceClass)) { for (SourceClass annotation : sourceClass.getAnnotations()) { String annName = annotation.getmetadata().getClassName(); if (!annName.startsWith("java") && !annName.equals(import.class.getName())) { collectimports(annotation, imports, visited); } } imports.addAll(sourceClass.getAnnotationAttributes(import.class.getName(), "value")); } }
这里的SourceClass是当前的配置类,什么是配置类?配置类就是包含@Configuration、@Service、@Component等注解的类,比如我们的spring boot启动类。
上面这段代码相当于是每个配置类都去找一遍是否包含@import注解。
出来接着上面的processimports方法
private void processimports(ConfigurationClass configClass, SourceClass currentSourceClass, CollectionimportCandidates, boolean checkForCircularimports) { if (importCandidates.isEmpty()) { return; } if (checkForCircularimports && isChainedimportOnStack(configClass)) { this.problemReporter.error(new CircularimportProblem(configClass, this.importStack)); } else { this.importStack.push(configClass); try { for (SourceClass candidate : importCandidates) { if (candidate.isAssignable(importSelector.class)) { // Candidate class is an importSelector -> delegate to it to determine imports Class> candidateClass = candidate.loadClass(); importSelector selector = BeanUtils.instantiateClass(candidateClass, importSelector.class); ParserStrategyUtils.invokeAwareMethods( selector, this.environment, this.resourceLoader, this.registry); if (selector instanceof DeferredimportSelector) { this.deferredimportSelectorHandler.handle( configClass, (DeferredimportSelector) selector); } else { String[] importClassNames = selector.selectimports(currentSourceClass.getmetadata()); Collection importSourceClasses = asSourceClasses(importClassNames); processimports(configClass, currentSourceClass, importSourceClasses, false); } } else if (candidate.isAssignable(importBeanDefinitionRegistrar.class)) { Class> candidateClass = candidate.loadClass(); importBeanDefinitionRegistrar registrar = BeanUtils.instantiateClass(candidateClass, importBeanDefinitionRegistrar.class); ParserStrategyUtils.invokeAwareMethods( registrar, this.environment, this.resourceLoader, this.registry); configClass.addimportBeanDefinitionRegistrar(registrar, currentSourceClass.getmetadata()); } else { // Candidate class not an importSelector or importBeanDefinitionRegistrar -> // process it as an @Configuration class this.importStack.registerimport( currentSourceClass.getmetadata(), candidate.getmetadata().getClassName()); processConfigurationClass(candidate.asConfigClass(configClass)); } } } catch (BeanDefinitionStoreException ex) { throw ex; } catch (Throwable ex) { throw new BeanDefinitionStoreException( configClass.getmetadata().getClassName() + "]", ex); } finally { this.importStack.pop(); } } }
这里也很简单,就是几个if else分支判断,
其中
if(candidate.isAssignable(importBeanDefinitionRegistrar.class))
是不是看到importBeanDefinitionRegistrar接口了,这里就是把上面找到的import类添加到
org.springframework.context.annotation.ConfigurationClass#importBeanDefinitionRegistrars这个Map中。
顺便说一下另外的
if (candidate.isAssignable(importSelector.class))这句就是我们熟悉用来解析spring boot自动装配用的,只不过它是importSelector类型,这种不放到Map中,后面会延迟单独处理它。
上面的查找过程,是每一个配置类都走一遍,如果有importBeanDefinitionRegistrar,就加到各自里面的Map先缓存起来。
既然存起来了,那肯定有用的地方是吧, 接着看。
先说明下ConfigurationClassPostProcessor这个类,很重要,它是解析所有配置类的,将配置类都转换成BeanDefinition对象,后续创建bean就靠它, 上面调用链路也是由它发起的。
org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions
其中有一句:
this.reader.loadBeanDefinitions(configClasses);
public void loadBeanDefinitions(SetconfigurationModel) { TrackedConditionevaluator trackedConditionevaluator = new TrackedConditionevaluator(); for (ConfigurationClass configClass : configurationModel) { loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionevaluator); } }
遍历每一个ConfigurationClass 配置类,因为我们前面已经是解析过importBeanDefinitionRegistrar了,所以这些配置类是包含importBeanDefinitionRegistrar类的。
private void loadBeanDefinitionsForConfigurationClass(
ConfigurationClass configClass, TrackedConditionevaluator trackedConditionevaluator) {
if (trackedConditionevaluator.shouldSkip(configClass)) {
String beanName = configClass.getBeanName();
if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
this.registry.removeBeanDefinition(beanName);
}
this.importRegistry.removeimportingClass(configClass.getmetadata().getClassName());
return;
}
if (configClass.isimported()) {
registerBeanDefinitionForimportedConfigurationClass(configClass);
}
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
loadBeanDefinitionsFromimportedResources(configClass.getimportedResources());
loadBeanDefinitionsFromRegistrars(configClass.getimportBeanDefinitionRegistrars());
}
loadBeanDefinitionsFromRegistrars(configClass.getimportBeanDefinitionRegistrars());
好了,这里终于要拿前面缓存好的Map了
private void loadBeanDefinitionsFromRegistrars(Mapregistrars) { registrars.forEach((registrar, metadata) -> registrar.registerBeanDefinitions(metadata, this.registry)); }
遍历每一个importBeanDefinitionRegistrar类,调用registerBeanDefinitions方法完成后续注册工作。



