spring源码:@Import注解

本文详细探讨了Spring框架中@Import注解的作用,包括如何引入bean、ImportSelector和ImportBeanDefinitionRegistrar接口的使用。通过源码分析,解释了@Import注解在配置类中的处理流程,涉及ImportSelector的递归解析以及ImportBeanDefinitionRegistrar的注册过程,最终将bean转换为BeanDefinition并存入BeanDefinitionMap。

目的

前面的文章@Bean源码解析有说到,将一个bean,转换成BeanDefinition,并存入BeanDefinitionMap有三种方式;本文,我们要说的是@Import注解这种方式;
@Import是用来引入bean的;和本文相关的,我们需要关注ImportSelector和ImportBeanDefinitionRegistrar

接口说明

ImportBeanDefinitionRegistrar该接口,定义了一个public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);

该方法的实现类,可以完成将bean添加到beanDefinitionMap中;因为在该方法中,可以获取到BeanDefinitionRegistry,只是:如果我们程序员自己去提供一个该接口的实现类,需要我们自己在接口实现类中,声明一个beanDefinition对象;并给beanDefinition对象设置属性
也可以在该方法中,修改已经存在于BeanDefinitionMap中的beanDefinition对象;

ImportSelector
该接口定义的方法,返回的是一个数组集合,我们只需要在实现类中定义我们要注入的bean的全类名,并放到return的集合中,即可;springboot的自动注入就是利用这个原理的,
通过SpringFactoriesLoader.loadFactoryNames获取到所有jar包中定义的要自动注入的bean对应的全类名;然后,spring会对所有要注入的bean进行解析;

源码

我前面的博客,有说到过,所有将bean转换为BeanDefinition的操作,都是在

org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry

这个方法中完成的,我们本次要说的@Import注解的处理,也是在这个方法内部完成的;

这个gif是postProcessBeanDefinitionRegistry方法内部的调用逻辑
我们直接来看processImports(configClass, sourceClass, getImports(sourceClass), true);这行代码完成的动作;因为这个方法是本篇文章所要关注的

解析Import注解

getImports(sourceClass):这个方法内部嵌套的比较简单,就是获取到当前配置类上所有的注解,然后获取到@Import注解对应的value,也即:import注入的类

我们接着来看org.springframework.context.annotation.ConfigurationClassParser#processImports这个方法的处理:
先说这个方法的整体处理逻辑:

Import注解引入的类,有三种情况

  1. ImportSelector:
    1.1 判断Import引入的ImportSelector的实现类是否是DeferredImportSelector的实现类;DeferredImportSelector这个接口,在springboot自动注入的时候有用到;可以看下图1 AutoConfigurationImportSelector的继承关系:

    1.2 如果是非DeferredImportSelector的实现类,就正常处理:ImportSelector的实现类中,return的全类名数组; 在这里, 会依次解析每个类,防止要注入的类中有ImportSelector和ImportBeanDefinitionRegistrar的实现类;
    对于ImportSelector实现类,返回的普通bean存放到了configurationClasses中 会在org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitions(java.util.Set)方法中初始化,完成bean到BeanDefinition的转换

  2. ImportBeanDefinitionRegistrar:
    这里的处理比较简单;将实现类的registrar对象和metadata存入到importBeanDefinitionRegistrars这个map中,也是在org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitions(java.util.Set)进行beanDefinition对象的生成

  3. 普通类(bean):
    存入到了configurationClasses这个集合中;如果ImportSelector实现类返回的bean就是一个普通bean,那就会在第一次递归调用processImports的时候,在第三步这里添加到集合中;否则,会一直递归调用,直到解析到import的是普通bean;

也即:对于ImportBeanDefinitionRegistrar的实现类,直接存入到了map集合中;对于ImportSelector的实现类,需要在解析return的所有bean,防止return的bean中还有ImportSelector或者ImportBeanDefinitionRegistrar的实现类

图1

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
@Import注解Spring框架中的一个注解,它用于将其他类或配置导入到当前类中。@Import可以单独使用,也可以和其他注解一起使用,例如@Configuration注解、ImportSelector接口和ImportBeanDefinitionRegistrar接口。 当@Import注解单独使用时,它可以直接将其他普通的类导入到当前类中,以便在当前类中可以使用被导入的类。 当@Import注解结合@Configuration注解、ImportSelector接口和ImportBeanDefinitionRegistrar接口使用时,在Spring Boot中是最常见的用法之一。举个例子,如果我们在一个类上使用@EnableAutoConfiguration注解,那么在该注解源码中会使用@Import注解来导入AutoConfigurationImportSelector类。这样,通过@EnableAutoConfiguration注解,我们可以自动配置应用程序的一些默认设置。 总结来说,@Import注解是用来将其他类或配置导入到当前类中的注解,可以单独使用,也可以和其他注解一起使用,常见的用法是结合@Configuration注解、ImportSelector接口和ImportBeanDefinitionRegistrar接口在Spring Boot中实现自动配置。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [@Import注解的四种使用方式](https://blog.youkuaiyun.com/bluemysky/article/details/128827769)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [@Import注解使用](https://blog.youkuaiyun.com/m0_55806905/article/details/127967036)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值