IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> spring @Import介绍 -> 正文阅读

[Java知识库]spring @Import介绍

文档翻译

指示要导入的一个或多个组件类——通常是@Configuration类。
提供与 Spring XML 中<import/>元素等效的功能。允许导入@Configuration类、 ImportSelector和ImportBeanDefinitionRegistrar实现,以及常规组件类(从 4.2 开始;类似于AnnotationConfigApplicationContext.register )

何时解析@Import

答:处理配置类时。具体代码分析如下:
ConfigurationClassParser#processConfigurationClass会调用
ConfigurationClassParser#doProcessConfigurationClass方法
, 在doProcessConfigurationClass中如下代码处理:(这一块属于ConfigurationClassPostProcessor相关的,这里不做介绍,简单可理解为扫描出的bean都会经过此处代码处理)

		// Process any @Import annotations
		processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

getImports就是递归查找sourceClass上的@Import注解的值,就不展开看了,只看处理方法processImports。

processImports 处理@Import

				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 = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
								this.environment, this.resourceLoader, this.registry);
						Predicate<String> selectorFilter = selector.getExclusionFilter();
						if (selectorFilter != null) {
							exclusionFilter = exclusionFilter.or(selectorFilter);
						}
						if (selector instanceof DeferredImportSelector) {
							this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
						}
						else {
							String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
							Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
							processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
						}
					}
					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 =
								ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
										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), exclusionFilter);
					}
				}
  • 候选类是一个ImportSelector,委托给ImportSelector以确定导入(导入其它bean)
  • 候选类是一个ImportBeanDefinitionRegistrar,委托给ImportBeanDefinitionRegistrar注册其他bean定义
  • 候选类不是ImportSelector或ImportBeanDefinitionRegistrar,将其作为@Configuration类处理。

ImportSelector处理

这里分为两种情况做了处理。

  • DeferredImportSelector(延期的的ImportSelector):ImportSelector的一种变体,在处理完所有@Configuration bean 后运行。当所选导入是@Conditional时,这种类型的选择器可能特别有用。
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

EnableAutoConfiguration上的 AutoConfigurationImportSelector就是这种类型。都说了在处理完所有@Configuration bean后才出处理DeferredImportSelector,所以这里的处理目前也很简单,就是包装了下放到了一个list集合中,真正的处理后续文章会说明(springboot starter)。(简化后代码)

		public void handle(ConfigurationClass configClass, DeferredImportSelector importSelector) {
			DeferredImportSelectorHolder holder = new DeferredImportSelectorHolder(configClass, importSelector);
			this.deferredImportSelectors.add(holder);
		}
  • 非DeferredImportSelector类型处理方式:调用importSelector接口方法selectImports()结果作为importSourceClasses ,然后又重新调用processImports 方法递归处理。这里有一点可以注意下,就是实例化ImportSelector代码,selectImports()实现里可以添加扩展。

ImportBeanDefinitionRegistrar处理

存入ConfigurationClass属性Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> importBeanDefinitionRegistrars中,后续会做真正的处理。处理就在ConfigurationClassPostProcessor#processConfigBeanDefinitions方法中。

this.reader.loadBeanDefinitions(configClasses);

@Configuration类型处理

Configuration处理会调用ConfigurationClassParser#processConfigurationClass,文章开头红色标识的。是的又开始了新一轮的循环。这里只是作为@Configuration类型处理,并不是说这个类上非得加上@Configuration注解,普通的bean也是可以的。只不过后续的解析过程中没有解析到@Import、@Bean等 而已

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-05-07 11:02:36  更:2022-05-07 11:04:15 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 23:43:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码