文章目录
前言
- 导入jar包中的类,交由 spring 容器所管理
- 我这里会用 Demo 中的 类名作为说明!!!,具体到了哪一步哪一步扫描谁,处理谁直接用类名 来表示,要是看的模糊的看一下类名
为什么使用@ Import
在平时的业务开发当中,将对象放入容器,使用 @Bean
和 @Component
基本就能够满足需求,但是@ Import
注解能够方便扩展功能,其实我觉得可以认为是一个插件一样的东西,简简单单的只需要加上这个注解就能开启功能,
例如:
我现在想要让我们的项目拥有开飞机的功能,单单开飞机就可能需要很多组件,这些组件必须存在,这个项目才能开飞机,那如果毎一个类上都加上 @Component
注解,到时候我不想要这个项目拥有开飞机功能,那是不是需要逐一的删除~~@Component~~注解,这时@Import
的注解就体现出来了,我只需要自定义一个注解@Enable飞机
,将飞机组件都加入到@import
里面,需要的时候只需要将 @Enable飞机
飞机加到个@Configuration
注解里面就好了
所需知识
指的是你需要对这些稍微有一个了解,最起码稍微知道一点里面的属性…,当然不知道也没问题.
- BeanDefinition
- ConfigurationClass
- SourceClass
@Import
@ComponentScan("vip.xjdai.annotation.Import.annotation")
public class ImportContext {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ImportContext.class);
}
}
@Configuration
@Import({ImportBean.class})
public class ImportConfiguration {}
// 假设这个 类 是一个jar 中的类,我们无法修改,但是又想让他被spring所管理如何做呢~那就利用 `@Import`注解好了
public class ImportBean {
}
注册@Configuration类
- new AnnotationConfigApplicationContext() 构造函数
- refresh() 刷新容器
- 执行 BeanFactoryPostProcessors,简单说是初始化一些 BeanFactoryPostProcessors
- PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(); 执行BeanFactoryPostProcessors,简单说是初始化一些BeanFactoryPostProcessors
- 执行ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry()方法
- 执行processConfigBeanDefinitions()–对package下的所有Classs 进行扫描预解析成BeanDefinition
- parse() --> parse() 进行解析—这里是处理
@ComponentScan
- processConfigurationClass()
- doProcessConfigurationClass()
protected final SourceClass doProcessConfigurationClass(
ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
throws IOException {
// 需要说明的是第一次扫描是将 `ImportConfiguration`放入到容器里面去,并不会将 `ImportConfiguration` 放入到容器中
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
// 循环所有 @ComponentScan
for (AnnotationAttributes componentScan : componentScans) {
// 去解析,去扫描所有符合条件的 Bean 并将其包装成 ScannedGenericBeanDefinition
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// 循环所有 BeanDefinitionHolder
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
// 获取原始的 BeanDefinitionHolder
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
// 如果是NUll
if (bdCand == null) {
// 将自身返回
bdCand = holder.getBeanDefinition();
}
// 检查是不是 @Configuration 、@Component、@ComponentScan、@Import、@ImportResource 注解,如果是则会进行递归~~~
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
}
- 需要说明的是第一次扫描是将
ImportConfiguration
放入到容器里面去,并不会将ImportConfiguration
放入到容器中 - 第一次递归也是将扫描好的
ImportConfiguration
包装成BeanDefinition,判断是不是 一些特定注解,由于我们的 Bean(ImportConfiguration)就是@Configuration ,所以条件符合那就进行递归调用
扫描@Import
- 这里是接着上面讲的递归,也就是如果判断是不是 一些特定注解才掉的这个方法,
protected final void parse(@Nullable String className, String beanName) throws IOException {
// 通过className 解析成 MetadataReader 对象 ,也就是元数据,这里的代码我就不贴了.. 简单来说我们传递一个Class 帮我们做了一些解析
MetadataReader reader = this.metadataReaderFactory.getMetadataReader(className);
//重新构建了一个 ConfigurationClass 对象
processConfigurationClass(new ConfigurationClass(reader, beanName), DEFAULT_EXCLUSION_FILTER);
}
- processConfigurationClass()
我精简了大量的代码,
protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
// 获取 SourceClass 这里是通过 Class 或者 ClassName 去获取 SourceClass(感兴趣自己去看一下吧)
SourceClass sourceClass = asSourceClass(configClass, filter);
do {
// 去处理 Configuration 相关的类,
sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
}
while (sourceClass != null);
//添加到configurationClasses中
this.configurationClasses.put(configClass, configClass);
}
- doProcessConfigurationClass() – 这里的代码我只贴了核心的,其他的都不符合条件全删了…
protected final SourceClass doProcessConfigurationClass(
ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
throws IOException {
// 这里处理 @Import
// getImports() 去获取 ImportConfiguration 这个类上 @Import 注解
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
return null;
}
- getImports()
private Set<SourceClass> getImports(SourceClass sourceClass) throws IOException {
Set<SourceClass> imports = new LinkedHashSet<>();
Set<SourceClass> visited = new LinkedHashSet<>();
collectImports(sourceClass, imports, visited);
return imports;
}
- collectImports
这里有一个递归的动作,等方法结束后都会去调用 imports.addAll()
private void collectImports(SourceClass sourceClass, Set<SourceClass> imports, Set<SourceClass> visited)
throws IOException {
if (visited.add(sourceClass)) {
// 循环 目标类 上所有注解,也包括注解上的所有注解,会将其包装成SourceClass
for (SourceClass annotation : sourceClass.getAnnotations()) {
// 获取注解名称
String annName = annotation.getMetadata().getClassName();
// 如果不是 Import 则进行下一次循环,
// 简单说判断了是不是包装成 Import了 比如很多@Enable***
if (!annName.equals(Import.class.getName())) {
// 进行递归,比如 @Enable***
collectImports(annotation, imports, visited);
}
}
//获取 @Import 注解上的属性,将其包装成 SourceClass 放入到集合当中
imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));
}
}
- getAnnotationAttributes
public Collection<SourceClass> getAnnotationAttributes(String annType, String attribute) throws IOException {
// 根据注解的 Name 获取到所有的属性
Map<String, Object> annotationAttributes = this.metadata.getAnnotationAttributes(annType, true);
// 属性如果是空则返回一个空,
// 如果没有包含这个属性 也会返回一个空
if (annotationAttributes == null || !annotationAttributes.containsKey(attribute)) {
return Collections.emptySet();
}
// 获取属性获取 ClassName 简单说获取的就是 ImportBean 的全限定类名
String[] classNames = (String[]) annotationAttributes.get(attribute);
Set<SourceClass> result = new LinkedHashSet<>();
// 循环所有的ClassName
for (String className : classNames) {
// getRelated() 就是根据 className 获取其Class 并且会包装成 SourceClass
result.add(getRelated(className));
}
return result;
}
处理@Import
- 会先通过 getImports() 获取 @Import 注解要导入的类
- 会将
ImportBean
认为是一个@Configuration
继续递归一遍…
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
boolean checkForCircularImports) {
//判断 有没有 @Import --这里的集合就是通过 getImports() 这个方法处理的
if (importCandidates.isEmpty()) {
return;
}
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
} else {
this.importStack.push(configClass);
try {
// 循环所有 @import 注解中的 Class 此时我们的 Class 是 `ImportBean`
for (SourceClass candidate : importCandidates) {
//判断 目标类 是不是实现了这个接口的
if (candidate.isAssignable(ImportSelector.class)) {
// 这里我暂时不说明,下面会有说明
} else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
// 这里我暂时不说明,下面会有说明
} else {
// 由于 既不是一个 ImportSelector、ImportBeanDefinitionRegistrar
// 则会 认为是一个 @Configuration....然后有会进行递归....
// 加入到 importStack 里面
this.importStack.registerImport(currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
// 调用 processConfigurationClass
// 继续递归...进行处理,注意一下 candidate.asConfigClass(configClass)
// 也就说会重新构建一个 ConfigurationClass(),然后进行递归,当递归结束,就会放入到Map中
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();
}
}
}
- asConfigClass
需要说明的是,当前的 this 是 ImportBean
而 importedBy 是 ImportConfiguration
public ConfigurationClass asConfigClass(ConfigurationClass importedBy) {
if (this.source instanceof Class) {
return new ConfigurationClass((Class<?>) this.source, importedBy);
}
//这里是重新改造了一个 ConfigurationClass
return new ConfigurationClass((MetadataReader) this.source, importedBy);
}
- new ConfigurationClass()
主要是将 ImportConfiguration
放入到集合当中,然后结束后放入Map中
public ConfigurationClass(MetadataReader metadataReader, @Nullable ConfigurationClass importedBy) {
this.metadata = metadataReader.getAnnotationMetadata();
this.resource = metadataReader.getResource();
// 将标注有 `@Import()` 注解的目标类,放到这个集合当中去... 这里后面会用到
this.importedBy.add(importedBy);
}
处理(组件)
- doProcessConfigurationClass() 这里是对
ImportBean
的处理 doProcessConfigurationClass
这个方法走完- 将其放入到
this.configurationClasses.put(configClass, configClass);
- 递归结束,也就是说结束了(组件的处理)这里我们可以简单的认为是对
ImportBean
处理结束~
问题
我们知道了,在扫描的时候会吧ImportBean
放入到Map中,那什么时候注册到容器中去的呢
我们假设所有流程走完了也就是说后面会去处理…
注册(组件)
- new AnnotationConfigApplicationContext() 构造函数
- refresh() 刷新容器
- 执行BeanFactoryPostProcessors(); 简单说是初始化一些BeanFactoryPostProcessors
- PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(); 执行BeanFactoryPostProcessors,简单说是初始化一些BeanFactoryPostProcessors
- 执行ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry() 方法
- 执行processConfigBeanDefinitions()----这个方法还没执行完呢~~~
- parse()–方法出栈
- parse() --方法出栈
- processConfigurationClass()–方法出栈
- doProcessConfigurationClass()–方法出栈
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
// 存放所有的 @Component、 @ComponentScan、@Import、@ImportResource、@Bean、Configuration类,需要注意的是这里的存放是已经注册过的..
// 那我们知道,其实这个方法还在初始化呀,在初始化的时候只会帮我们装载了 @ComponentScan 的对象,这里不深究..
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
// alreadyParsed 用于判断是否处理过
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
// 去处理
parser.parse(candidates);
//校验
parser.validate();
// 这里是由 parser.getConfigurationClasses() 是在执行完 parse-->parse-->processConfigurationClass 执行完放进去滴~~
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// 如果 reader是空就new 一个处理
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 集合,
candidates.clear();
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
Set<String> alreadyParsedClasses = new HashSet<>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
// Clear cache in externally provided MetadataReaderFactory; this is a no-op
// for a shared cache since it'll be cleared by the ApplicationContext.
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
调用loadBeanDefinitions
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
// 循环 所有的 ConfigurationClass
for (ConfigurationClass configClass : configurationModel) {
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
调用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;
}
// 判断是否存在 imported 这里上面已经详细分析过了.
if (configClass.isImported()) {
//现在的关注点是这里
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
// 遍历配置类上所有的@Bean方法返回的bean并注册
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
// 导入资源配置如:@ImportResource(locations={"classpath:spring-beans.xml"}
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
// 这个地方下面在细谈~~
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
调用 registerBeanDefinitionForImportedConfigurationClass
private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
// 获取元数据
AnnotationMetadata metadata = configClass.getMetadata();
// 将元数据包装成 AnnotatedGenericBeanDefinition
AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);
// 解析其 @Scope
ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
configBeanDef.setScope(scopeMetadata.getScopeName());
// 生成BeanName
String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata);
// 将 Name 和 AnnotatedGenericBeanDefinition 进行封装
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
// 根据 @Scope 是否进行代理
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 进行注册,这里的注册也就是说是注册 我们的(组件)
this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
// 将Name 设置一下
configClass.setBeanName(configBeanName);
}
流程图
ImportSelector
@ComponentScan
public class ImportSelectorContext {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ImportSelectorContext.class);
}
}
class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{ImportBeanA.class.getName(), ImportBeanB.class.getName()};
}
}
@Import({MyImportSelector.class})
@Configuration
class ImportConfiguration {
}
class ImportBeanB {
}
class ImportBeanA {
}
注册@Configuration类
跟 @import 基本一直
扫描@Import
跟 @import 基本一直
protected final SourceClass doProcessConfigurationClass(
ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
throws IOException {
// 这里处理 @Import 因为 ImportConfiguration 这个类上有这个注解
// 1. 会先通过 getImports() 获取有没有 @Import注解
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
return null;
}
- getImports() ,通过这个方法获取到 MyImportSelector
private Set<SourceClass> getImports(SourceClass sourceClass) throws IOException {
Set<SourceClass> imports = new LinkedHashSet<>();
Set<SourceClass> visited = new LinkedHashSet<>();
collectImports(sourceClass, imports, visited);
return imports;
}
处理@Import
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
boolean checkForCircularImports) {
//判断 有没有 Import
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) {
//判断是不是实现了这个接口的
if (candidate.isAssignable(ImportSelector.class)) {
// 获取到目标类~~
Class<?> candidateClass = candidate.loadClass();
// 去创建这个类,利用反射
ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
this.environment, this.resourceLoader, this.registry);
// 去执行 exclusion 方法,排除方法,可自行演示
Predicate<String> selectorFilter = selector.getExclusionFilter();
if (selectorFilter != null) {
exclusionFilter = exclusionFilter.or(selectorFilter);
}
//如果当前类是 DeferredImportSelector 的实现,则加入到 deferredImportSelectors
if (selector instanceof DeferredImportSelector) {
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
} else {
//如果不是, 则调用 processImports 进行处理,也就是我们实现的那个类~~~
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
// 将 其包装成 SourceClass 然后进行递归..
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
}
//判断是不是实现这个接口的
} else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
// 省略~~~
} else {
// 省略这里上面 讲过了
}
}
} catch (Throwable ex) {
}
}
}
- 当执行完 selectImports() 这个方法后,就获取到两个类的Class 全限定类名
- 这个方法的实现是由 我们自己定义的 MyImportSelector 的实现
- 然后去调用 asSourceClasses 执行完这个方法后, 会将 我们的类 包装成 SourceClass
- 然后执行递归 processImports
- 执行递归的时候,如果 我们定义的 BeanA 和BeanA 有实现 ImportBeanDefinitionRegistrar 或者 ImportSelector 的时候又会走一边,反正最终会走到 else 里面,也就说最终会将其认为是一个Configuration 类,执行一边,然后流程嘛就跟上面的差不多了…
创建(组件)
指的是@Import("")
导入的组件什么时候创建对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZMvCYDZi-1597830774884)(//img.xjdai.vip/202007231724_452.png)]
后续处理
- 递归 processImports ,需要注意的是
importSourceClasses
是有2个类的,是我们添加到String[]{}
两个类 - 然后会走到 processConfigurationClass,对
importBeanA
、importBeanB
也就是说会递归两次~ - 然后将这两Map放到集合当中去
注册
- new AnnotationConfigApplicationContext() 构造函数
- refresh() 刷新容器
- 执行BeanFactoryPostProcessors(); 简单说是初始化一些BeanFactoryPostProcessors
- PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(); 执行BeanFactoryPostProcessors,简单说是初始化一些BeanFactoryPostProcessors
- 执行ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry() 方法
- 执行processConfigBeanDefinitions()
- loadBeanDefinitions() – 注册
private void loadBeanDefinitionsForConfigurationClass(
ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
// 是不是 Imported 的组件
if (configClass.isImported()) {
//注册 组件
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
}
ImportBeanDefinitionRegistrar
//定义配置类
@Configuration
@Import(MyImportBeanDefinitionRegistrar.class)
public class ImportBeanDefinitionRegistrarConfig {}
//定义注册类
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//importingClassMetadata 当前类的元数据
// registry.containsBeanDefinition() //判断容器中是否有这个Bean
// registry.getBeanDefinition() //根据名字获取 BeanDefinition
registry.registerBeanDefinition("aaa", new RootBeanDefinition(ImportBeanDefinitionRegistrarBeanDemoA.class));// 注册一个Bean
}
}
// 定义要被注册的类
public class ImportBeanA {
}
注册@Configuratio
跟最开始的基本一致
扫描@Import
跟最开始的基本一致
处理@Import
这里的处理可以认为是处理MyImportBeanDefinitionRegistrar
我们自定义的类
- 会先通过 getImports() 获取有没有 @Import 注解
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
boolean checkForCircularImports) {
//判断 有没有 Import
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) {
//判断是不是实现了这个接口的
if (candidate.isAssignable(ImportSelector.class)) {
// 省略~~
} else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
// 也就是说 通过 ImportBeanDefinitionRegistrar 来创建 了这个 Bean
Class<?> candidateClass = candidate.loadClass();
//去 实例化 这个对象
ImportBeanDefinitionRegistrar registrar =
ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
this.environment, this.resourceLoader, this.registry);
// 放入到一个 importBeanDefinitionRegistrars Map 中去~~~
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
} else {
// 省略~~
}
}
} catch (Throwable ex) {
}
}
}
创建(组件)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wp3VZEeV-1597830774890)(//img.xjdai.vip/202007240934_128.png)]
组件注册
- new AnnotationConfigApplicationContext() 构造函数
- refresh() 刷新容器
- 执行BeanFactoryPostProcessors(); 简单说是初始化一些BeanFactoryPostProcessors
- PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(); 执行BeanFactoryPostProcessors,简单说是初始化一些BeanFactoryPostProcessors
- 执行ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry() 方法
- 执行processConfigBeanDefinitions()
- loadBeanDefinitions() – 注册
private void loadBeanDefinitionsForConfigurationClass(
ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
// 这里是去注册实现了 ImportBeanDefinitionRegistrars 接口的
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
- registrar就是 MyImportBeanDefinitionRegistrar 这个类,这个类去调用这个接口
private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
registrars.forEach((registrar, metadata) ->
registrar.registerBeanDefinitions(metadata, this.registry, this.importBeanNameGenerator));
}
//接口内部做了一个实现 1.8特性~~
default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry,
BeanNameGenerator importBeanNameGenerator) {
//真正的目标方法
registerBeanDefinitions(importingClassMetadata, registry);
}
DeferredImportSelector
本类没有深入研究,就不写了,大致写一下
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
boolean checkForCircularImports) {
//判断 有没有 @Import
if (importCandidates.isEmpty()) {
return;
}
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
} else {
this.importStack.push(configClass);
try {
// 循环所有 @import 注解中的 Class
for (SourceClass candidate : importCandidates) {
//判断 目标类 是不是实现了这个接口的
if (candidate.isAssignable(ImportSelector.class)) {
// Candidate class is an ImportSelector -> delegate to it to determine imports
// 获取目标类的Class
Class<?> candidateClass = candidate.loadClass();
// 去创建 这个 目标类,利用反射
ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
this.environment, this.resourceLoader, this.registry);
Predicate<String> selectorFilter = selector.getExclusionFilter();
if (selectorFilter != null) {
exclusionFilter = exclusionFilter.or(selectorFilter);
}
//如果当前类是DeferredImportSelector 的实现,则加入到deferredImportSelectors
if (selector instanceof DeferredImportSelector) {
// 放入到一个集合当中去
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
} else {
//省略
}
//判断是不是实现这个接口的
} else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
//省略
} else {
//省略
}
}
} catch (BeanDefinitionStoreException ex) {
throw ex;
} catch (Throwable ex) {
}
}
}
什么时候调用呢,我看到的在所有的
- new AnnotationConfigApplicationContext() 构造函数
- refresh() 刷新容器
- 执行 BeanFactoryPostProcessors,简单说是初始化一些 BeanFactoryPostProcessors
- PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(); 执行BeanFactoryPostProcessors,简单说是初始化一些BeanFactoryPostProcessors
- 执行ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry()方法
- 执行processConfigBeanDefinitions()–对package下的所有Classs 进行扫描预解析成BeanDefinition
- parse() – 在这个方法体里面结束后执行的
public void parse(Set<BeanDefinitionHolder> configCandidates) {
//循环所有 BeanDefinitionHolder
for (BeanDefinitionHolder holder : configCandidates) {
// 获取 BeanDefinition
BeanDefinition bd = holder.getBeanDefinition();
try {
// 这里根据Bean定义的不同类型走不同的分支,但是最终都会调用到方法 processConfigurationClass(ConfigurationClass configClass)
if (bd instanceof AnnotatedBeanDefinition) {
//将 元数据和Bean取出来
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
// 如果是 AbstractBeanDefinition 并且存在 BeanClass 因为我们知道 有可能 BeanClass 是String类型
} else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
} else {
// 如果上面判断都没过则就会走这里
parse(bd.getBeanClassName(), holder.getBeanName());
}
} catch (BeanDefinitionStoreException ex) {
throw ex;
} catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
}
}
// 执行找到的 DeferredImportSelector
// DeferredImportSelector 是 ImportSelector 的一个变种。
// ImportSelector 被设计成其实和 @Import 注解的类同样的导入效果,
// 但是实现 ImportSelector 的类可以条件性地决定导入哪些配置。
// DeferredImportSelector 的设计目的是在所有其他的配置类被处理后才处理。
// 这也正是该语句被放到本函数最后一行的原因。
this.deferredImportSelectorHandler.process();
}
- 也就是说是在最后一行执行的
后续说明
- 其实只要读懂了 @import 也就说最开始的那个东东,后面的这些基本相差不是特别大…