@Import注解源码分析
Bean的生产,首先是为bean定义出一个beanDefinition(bean定义),再根据beanDefinition创建bean, beanDefinition存入beanDifinitionMap之前会创建ConfigurationClass类,spring根据ConfigurationClass的信息,将beanDefinition存储map中,beanDefinition包括很多的信息,例如是否为单例,多例,是否为懒加载,DependsOn(创建bean之前需要创建的bean),是否@Primary,autowireMode,beanClass,initMethodName等等的信息.所有的bean定义都会存放进bean工厂的beanDefinitionMap中,后续会遍历map中的beanDefinition,并创建bean,如果beanDefinitionMap中不存在则不会创建.@Import的作用和@Component的作用有一些相似,都会创建bean.了解这些可以帮助我们分析@Import注解,本文也会结合源码分析@Import注解
Import只有一个变量 value
@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();
}
@Import首先是在
ConfigurationClassParser#doProcessConfigurationClass的processImports(configClass, sourceClass, getImports(sourceClass), filter, true);被解析,此方法只是把类的信息封装进ConfigruationClass中
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, boolean checkForCircularImports) {
if (importCandidates.isEmpty()) {
return;
}
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
this.importStack.push(configClass);
try {
//获取Import导入进来的类
for (SourceClass candidate : importCandidates) {
//判断该组件是不是实现了ImportSelector的
if (candidate.isAssignable(ImportSelector.class)) {
// Candidate class is an ImportSelector -> delegate to it to determine imports
Class<?> candidateClass = candidate.loadClass();
//实例化实现SelectImport接口的类
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
ParserStrategyUtils.invokeAwareMethods(
selector, this.environment, this.resourceLoader, this.registry);
if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
this.deferredImportSelectors.add(
new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
}
else {
//调用ImportSelector的selectImports方法,返回String数组,类的全类名称
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
//String[]返回的类可能实现了ImportSelector或者ImportBeanDefinitionRegistrar接口,也有可能是
//一个普通的类,这里递归解析,直到为一个普通的类,或者说扫面到不实现ImportSelector接口的类
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
processImports(configClass, currentSourceClass, importSourceClasses, false);
}
}
//判断类是否实现了ImportBeanDefinitionRegistrar接口,不调用接口的实现方法,而是存入进configClass中
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
// Candidate class is an ImportBeanDefinitionRegistrar ->
// delegate to it to register additional bean definitions
Class<?> candidateClass = candidate.loadClass();
//实例化类
ImportBeanDefinitionRegistrar registrar =
BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
ParserStrategyUtils.invokeAwareMethods(
registrar, this.environment, this.resourceLoader, this.registry);
//保存我们的类到configClass中,后续会被调用
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
else {
//如果没有实现上面两个接口, candidate.asConfigClass(configClass)标注importedBy,后续判断是否是通过@Import导入的
//继续执行processConfigurationClass方法,可以点进去看一下,这里不扩展了, processConfigurationClass的作用就是
//类是否标注了@Component@ PropertySources@ ComponentScans@ ImportResource@Import这些注解,并根据相应的注解解析类
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
}
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configClass.getMetadata().getClassName() + "]", ex);
}
finally {
this.importStack.pop();
}
}
}
通过上面的源码分析,分析@Import导入的类是否实现了ImportSelector和BeanDefinitionRegistrar接口,如果同时实现只解析ImportSelector
上面只是将一些信息存放到configclass中,代码执行到ConfigurationClassPostProcessor # processConfigBeanDefinitions 方法的this.reader.loadBeanDefinitions(configClasses);这段代码是开始解析configClasses,通过for循环遍历所有的configClasses;目的是向beanDefinitionMap注册beanDefinition
ConfigurationClassBeanDefinitionReader# loadBeanDefinitionsForConfigurationClass方法
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;
}
//这里就是解析@Import类,上面提到过importedBy,这里就会解析
if (configClass.isImported()) {
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
//这里解析继承ImportBeanDefinitionRegistrars类,调用registerBeanDefinitions方法,其中两个入参AnnotationMetadata importingClassMetadata和 BeanDefinitionRegistry registry ,importingClassMetadata为原类信息,注意不是ImportBeanDefinitionRegistrars的实现类,是标注@Import类的元信息 registry可以手动的向beanDefinitionMap中注册beanDefinition
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
registerBeanDefinitionForImportedConfigurationClass方法
private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
//获取配置类的元信息
AnnotationMetadata metadata = configClass.getMetadata();
//构建beanDefinition
AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);
//设置scope
ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
configBeanDef.setScope(scopeMetadata.getScopeName());
//获取bean的名称
String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
//处理我们的JRS250组件的
AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata);
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
//注册我们的bean定义到我们的容器中
this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
configClass.setBeanName(configBeanName);
if (logger.isDebugEnabled()) {
logger.debug("Registered bean definition for imported class '" + configBeanName + "'");
}
}
经过上面的分析,大致的了解@Import的机制,下面对分析@Import的使用
- A没有实现ImportBeanDefinitionRegistrar和ImportSelector两个接口
A将会存放进IOC容器中
- A实现ImportSelector
A类不会存放进IOC容器中,调用selectImprots方法,Run存放进IOC容器中
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{Run.class.getName ()};
}
- A类实现ImportBeanDefinitionRegistrar接口
A类依旧不会存入IOC容器中,在调用registerBeanDefinitions方法的时候将Walk存放进IOC容器中,并设置beanName为walk
当然这里可以操作beanDefinition我们就可以做很多的事,设置bean单例还是多例,是否为懒加载,dependsOn等很多的信息.
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
GenericBeanDefinition beanDefinition=new GenericBeanDefinition ();
beanDefinition.setBeanClass(Walk.class);
registry.registerBeanDefinition("walk",beanDefinition);
}
- @Import 配置 ImportAware使用
可以看我分享的文章 https://www.jianshu.com/p/8378b9f491ae