一、理论
1、@Import 作用
@Import 主要有两个作用,第一个是单纯的注册 beanDefinition,用于后续 bean 的加载;第二个是注册配置类,即该类会跟启动类一样,作为配置类加载,在代码中的形式为以该类封装的对象作为参数调用 doProcessConfigurationClass();
二、原理
1、如何执行到 processImports();
以 SpringBoot 的启动流程为例:SpringApplication.run(App.class,args);
abstractApplicationContext.refresh(); 中执行模板方法 invokeBeanFactoryPostProcessor();
invokeBeanFactoryPostProcessor(); 中执行 configurationClassPostProcessor.postProcessBeanDefinitionRegistry(); 注册 beanDefinition,
configurationClassPostProcessor.postProcessBeanDefinitionRegistry(); 中会执行 configurationClassParser.doProcessConfigurationClass(); 执行配置类的加载工作,如解析 @PropertySources、@ComponentScan、@Import、@Bean
configurationClassParser.doProcessConfigurationClass(); 中会执行 processImports();
2、processImports(); 逻辑
首先以执行启动类(App.java)的加载工作为例,首先收集到启动类上所有的 @Import 中的 value 属性值,即 class 对象,启动类上有[AutoConfigurationImportSelector.class],遍历每一个 class 对象,
第一步,判断该 class 是否实现 ImportSelector 接口,如果实现接口,执行 selectImports(); 返回类的全类名的字符串类型的数组,如[“com.A”,“com.B”],该数组中的每一个类作为参数继续执行 processImports(); 相当于启动类上又多了个 Import 注解:@Import({A.class,B.class}),但是 AutoConfigurationImportSelector 类有些特殊,它实现了 DeferredImportSelector 接口,执行的是 handle(); 但原理跟 selectImports(); 中的一致,通过 springfactoriesLoader.loadFactoryName(EnableAutoConfiguration.class); 加载所有 spring.factories文件中 EnableAutoConfiguration 的实现类
第二步,判断 该 class 是否实现 ImportBeanDefinitionRegistrar 接口,如果实现,执行 registerBeanDefinitions(); 注册 beanDefinition
第三步,即该 class 既不实现 ImportSelector,又不实现 ImportBeanDefinitionRegistrar,则该类作为配置类被执行,即以该类封装的对象作为参数执行 doProcessConfigurationClass();
三、使用
1、通过在配置类加上 @Import(A.class); 的方式,将 A 以配置类被加载,其中要求 A 既不实现 ImportSelector,又不实现 ImportBeanDefinitionRegistrar;
2、通过在配置类加上 @Import(B.class); 的方式,将 B 封装为 beanDefinition 注册到 beanFactory,用于后续 bean 的加载,其中要求 B 实现 ImportBeanDefinitionRegistrar
3、如果要求同时加载多个配置类、注册多个 beanDefinition,在配置类加上 @Import(C.class); 其中 C 实现 ImportSelector 接口。