目录
1、ConfigurationClassPostProcessor
4.2 ImportBeanDefinitionRegistrar
一、概述
@Import:用来向ioc容器注册组件。
注意:@Import只是向容器注册添加组件的相关信息,组件还未实例化,后续由容器进行实例化。
value数组值:
普通组件类、实现ImportSelector接口的实现类、实现ImportBeanDefinitionRegistrar接口的实现类

1、普通组件类:直接向容器注册组件,组件的id为组件的全限定类名,若是组件是一个配置类,则配置类内的组件(若配置类定义了内部类,也会扫描内部类判断是否加载该内部类)也会被注册到容器中
2、实现ImportSelector接口的实现类:通过实现selectImports方法返回组件的全限定类名数组,组件的id为组件的全限定类名
public class MyImportSelector implements ImportSelector {
/**
*
* @param importingClassMetadata 当前标识Import注解的类的所有注解信息
* @return 返回组件的全类名
*/
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.mzp.component.service.Red"};
}
}
3、实现ImportBeanDefinitionRegistrar接口的实现类:通过实现registerBeanDefinitions方法,可自定义向容器注册组件,可指定组件id
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/**
*
* @param importingClassMetadata 标识Import注解的类的所有注解信息
* @param registry Bean定义的注册类
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(RainRow.class);
registry.registerBeanDefinition("rain",rootBeanDefinition);
}
}
二、底层解析
1、ConfigurationClassPostProcessor
用来解析标识@Configuration配置类。
创建ioc容器时将ConfigurationClassPostProcessor注册到容器中,这是一个BeanDefinitionRegistryPostProcessor实现类,在refresh方法中运行invokeBeanDefinitionRegistryPostProcessors方法时,调用ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法里的processConfigBeanDefinitions方法去解析容器已注册的标识@Configuration的配置类

processConfigBeanDefinitions方法创建ConfigurationClassParser对象去解析@Configuration配置类的信息,包括解析注解@Import信息

2、ConfigurationClassParser
在parse方法中调用processConfigurationClass方法

processConfigurationClass方法通过循环调用doProcessConfigurationClass方法来解析当前配置类和配置类的父类信息

3、doProcessConfigurationClass
doProcessConfigurationClass方法解析多个spring注解,例如
@PropertySource、@ComponentScan、@Import、@ImportResource、@Bean、解析内部类信息等
解析内部类
定位到如图processImports方法,该方法就是实际用来解析@Import注解

getImports方法返回所有@Import注解的value集合,getImports方法通过collectImports方法获取当前组件标识@Import的value集合,包括元注解内部的@Import的value集合

4、processImports
在processImports方法中遍历已得到@Import的value集合importCandidates,判断每个value属于哪种类型
4.1 ImportSelector
若是value实现了ImportSelector接口,则先通过容器工具类创建对象,然后调用对象的selectImports方法得到导入组件数组importClassNames,继续递归调用processImports方法解析每个导入组件

4.2 ImportBeanDefinitionRegistrar
若是value实现了ImportBeanDefinitionRegistrar接口, 创建该对象,将对象添加到当前类的importBeanDefinitionRegistrars集合中

在后续解析完所有的@Configuration配置类后,调用ConfigurationClassPostProcessor的loadBeanDefinitions方法注册每个配置组件类到容器时,

调用loadBeanDefinitionsForConfigurationClass方法的loadBeanDefinitionsFromRegistrars方法运行当前类的importBeanDefinitionRegistrars集合的registerBeanDefinitions方法


4.3 普通组件类
当前value都没实现ImportSelector、ImportBeanDefinitionRegistrar接口时,将它当成一个配置类继续调用processConfigurationClass方法解析该配置类

三、测试类
@Test
public void test15(){
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ImportConfig.class);
}
package com.mzp.component.myimport;
import com.mzp.component.service.RainRow;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/**
*
* @param importingClassMetadata 标识Import注解的类的所有注解信息
* @param registry Bean定义的注册类
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(RainRow.class);
registry.registerBeanDefinition("rain",rootBeanDefinition);
}
}
package com.mzp.component.myimport;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
public class MyImportSelector implements ImportSelector {
/**
*
* @param importingClassMetadata 当前标识Import注解的类的所有注解信息
* @return 返回组件的全类名
*/
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.mzp.component.service.Red"};
}
}
package com.mzp.component.myimport;
public class Test {
public Test(){
System.out.println("Test()");
}
}
package com.mzp.component.config;
import com.mzp.component.myimport.MyImportBeanDefinitionRegistrar;
import com.mzp.component.myimport.MyImportSelector;
import com.mzp.component.myimport.Test;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import(value = {Test.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class ImportConfig {
}
本文详细解析了Spring框架中@Import注解的工作原理,从配置类的解析过程开始,逐步深入到ConfigurationClassPostProcessor、ConfigurationClassParser、doProcessConfigurationClass和processImports方法的执行细节。讲解了ImportSelector和ImportBeanDefinitionRegistrar接口的使用,以及如何通过这两个接口自定义向容器注册组件。最后通过测试类展示了实际应用。
976

被折叠的 条评论
为什么被折叠?



