@Import
- @Import
- 一、基本信息
- 二、注解描述
- 三、注解源码
- 四、主要功能
- 五、最佳实践
- 六、时序图
- 七、源码分析
- 八、注意事项
- 九、总结
- 最佳实践总结
- 源码分析总结
一、基本信息
✒️ 作者 - Lex 📝 博客 - 我的CSDN 📚 文章目录 - 所有文章 🔗 源码地址 - @Import源码
二、注解描述
@Import
是 Spring 框架的核心注解,用于导入配置类或组件到当前的 Spring 上下文中。它可以用于导入常规的 @Configuration
类、常规组件类,或实现了 ImportSelector
和 ImportBeanDefinitionRegistrar
接口的类。ImportSelector
允许根据条件动态地选择要导入的组件,而 ImportBeanDefinitionRegistrar
提供了一种以编程方式注册bean的方法。使用 @Import
注解,我们可以更灵活、模块化地组织 Spring 的配置,确保上下文中有所需的所有组件和配置。
三、注解源码
@Import
是 Spring 框架自 3.0 版本开始引入的一个核心注解。允许我们导入一个或多个组件类,这些类通常是 @Configuration
类。它在功能上相当于 Spring XML 中的 元素,导入类型
@Configuration
类、ImportSelector
、ImportBeanDefinitionRegistrar
的实现以及其他常规组件类,在导入的 @Configuration
类中声明的 bean 定义应使用 @Autowired
进行注入。
/**
* 表示要导入的一个或多个组件类 —— 通常是
* Configuration @Configuration 类。
*
* 提供与Spring XML中的 元素相同的功能。
* 允许导入 @Configuration 类、ImportSelector 和
* ImportBeanDefinitionRegistrar 的实现,以及常规组件
* 类 (从 4.2 开始;与 AnnotationConfigApplicationContext#register 相似)。
*
* 在导入的 @Configuration 类中声明的 @Bean 定义应通过
* org.springframework.beans.factory.annotation.Autowired @Autowired 注入。
* 可以自动注入bean本身,也可以自动注入声明bean的配置类实例。
* 后者允许在 @Configuration 类方法之间进行明确的、IDE友好的导航。
*
* 可以在类级别声明或作为元注解。
*
* 如果需要导入XML或其他非-@Configuration 的bean定义资源,
* 请改用 ImportResource @ImportResource 注解。
*
* @author Chris Beams
* @author Juergen Hoeller
* @since 3.0
* @see Configuration
* @see ImportSelector
* @see ImportBeanDefinitionRegistrar
* @see ImportResource
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
/**
* 要导入的 Configuration @Configuration、ImportSelector、
* ImportBeanDefinitionRegistrar 或常规组件类。
*/
Class[] value();
}
四、主要功能
导入配置类
- 允许一个
@Configuration
类引入另一个@Configuration
类。
导入选择器
- 通过实现
ImportSelector
接口,可以动态地选择和导入配置类。
手动注册Bean
- 通过实现
ImportBeanDefinitionRegistrar
接口,可以在运行时手动注册 bean。
导入常规组件类
- 从 Spring 4.2 开始,还可以导入常规的组件类。
五、最佳实践
首先来看看启动类入口,上下文环境使用AnnotationConfigApplicationContext
(此类是使用Java注解来配置Spring容器的方式),构造参数我们给定了一个MyConfiguration
组件类,然后遍历并打印所有的bean定义名。
public class ImportApplication {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);
for (String beanDefinitionName : context.getBeanDefinitionNames()) {
System.out.println("beanName = " + beanDefinitionName);
}
}
}
使用@Import
注解允许导入其他组件或配置到当前的配置类。在 MyConfiguration
类中,它导入了四个不同的组件或选择器,第一个是MyBean.class
一个常规Bean组件。第二个是MyImportSelector.class
一个实现了 ImportSelector
的类,用于动态选择并导入配置。第三个是MyDeferredImportSelector.class
一个实现了 DeferredImportSelector
的类,用于延迟地选择并导入配置。第四个是MyImportBeanDefinitionRegistrar.class
一个实现了 ImportBeanDefinitionRegistrar
的类,用于手动注册bean。
@Configuration
@Import({MyBean.class, MyImportSelector.class, MyDeferredImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MyConfiguration {
}
MyImportSelector
类提供了一种动态导入 MyBeanA
组件的机制。确保 MyBeanA
被加入到Spring的上下文中。
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{MyBeanA.class.getName()};
}
}
MyDeferredImportSelector
类提供了一种延迟导入 MyBeanB
组件的机制,确保 MyBeanB
被添加到Spring的上下文中。与普通的 ImportSelector
不同,DeferredImportSelector
允许在Spring处理完所有其他配置类之后再进行导入,从而确保某些特定的处理顺序。
public class MyDeferredImportSelector implements DeferredImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{MyBeanB.class.getName()};
}
}
MyImportBeanDefinitionRegistrar
类提供手动注册 MyBeanC
组件到Spring容器的方法,而不依赖于组件扫描或其他自动配置机制。确保 MyBeanC
被添加到Spring的上下文中。
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
RootBeanDefinition beanDefinition = new RootBeanDefinition(MyBeanC.class);
registry.registerBeanDefinition(MyBeanC.class.getName(), beanDefinition);
}
}
使用@Import
注解和其相关的选择器或注册器来将这些bean类导入到Spring上下文中
public class MyBean {
}
public class MyBeanA {
}
public class MyBeanB {
}
public class MyBeanC {
}
六、时序图
sequenceDiagram
participant ImportApplication
participant AnnotationConfigApplicationContext
participant AbstractApplicationContext
participant PostProcessorRegistrationDelegate
participant ConfigurationClassPostProcessor
participant ConfigurationClassParser
participant DeferredImportSelectorHandler
participant DeferredImportSelectorGroupingHandler
participant DeferredImportSelectorGrouping
participant DefaultDeferredImportSelectorGroup
participant ConfigurationClassBeanDefinitionReader
participant MyImportSelector
participant MyDeferredImportSelector
participant MyImportBeanDefinitionRegistrar
participant DefaultListableBeanFactory
ImportApplication->>AnnotationConfigApplicationContext:AnnotationConfigApplicationContext(componentClasses)初始化上下文
AnnotationConfigApplicationContext->>AbstractApplicationContext:refresh()刷新上下文
AbstractApplicationContext->>AbstractApplicationContext:invokeBeanFactoryPostProcessors(beanFactory)调用BeanFactory的后处理器
AbstractApplicationContext->>PostProcessorRegistrationDelegate:invokeBeanFactoryPostProcessors(beanFactory,beanFactoryPostProcessors)委托调用BeanFactory的后处理器
PostProcessorRegistrationDelegate->>PostProcessorRegistrationDelegate:invokeBeanDefinitionRegistryPostProcessors(postProcessors,registry,applicationStartup)执行BeanDefinition的注册后处理器
PostProcessorRegistrationDelegate->>ConfigurationClassPostProcessor:postProcessBeanDefinitionRegistry(registry)处理配置类
ConfigurationClassPostProcessor->>ConfigurationClassPostProcessor:processConfigBeanDefinitions(registry)处理配置类bean的定义
ConfigurationClassPostProcessor->>ConfigurationClassParser:new ConfigurationClassParser()创建配置类解析器
ConfigurationClassParser-->>ConfigurationClassPostProcessor:返回parser
ConfigurationClassPostProcessor->>ConfigurationClassParser:parser.parse(candidates)解析候选类
ConfigurationClassParser->>ConfigurationClassParser:parse(metadata,beanName)进一步解析类元数据
ConfigurationClassParser->>ConfigurationClassParser:processConfigurationClass(configClass,filter)处理@Configuration类
ConfigurationClassParser->>+ConfigurationClassParser:doProcessConfigurationClass(configClass, sourceClass, filter)实际处理配置类
ConfigurationClassParser-->>-ConfigurationClassParser:返回SourceClass
ConfigurationClassParser->>+ConfigurationClassParser:processImports(configClass, sourceClass, importCandidates, filter, true)处理导入
ConfigurationClassParser->>MyImportSelector:selectImports(importingClassMetadata)调用自定义的导入选择器
MyImportSelector-->>ConfigurationClassParser:返回Bean数组
ConfigurationClassParser->>DeferredImportSelectorHandler:process()处理延迟导入选择器
DeferredImportSelectorHandler->>DeferredImportSelectorGroupingHandler:processGroupImports()处理组导入
DeferredImportSelectorGroupingHandler->>DeferredImportSelectorGrouping:getImports()获取导入
DeferredImportSelectorGrouping->>DefaultDeferredImportSelectorGroup:process(metadata,selector)处理默认延迟导入选择器的组
DefaultDeferredImportSelectorGroup->>MyDeferredImportSelector:selectImports(importingClassMetadata) 调用自定义的导入选择器
MyDeferredImportSelector-->>DefaultDeferredImportSelectorGroup:返回Bean数组,存储在imports字段中
DeferredImportSelectorGrouping->>DefaultDeferredImportSelectorGroup:selectImports()选择导入
DeferredImportSelectorGrouping-->>DeferredImportSelectorGroupingHandler:返回Iterable
DeferredImportSelectorGroupingHandler->>ConfigurationClassParser:processImports(configClass, sourceClass, importCandidates, filter, true) 再次处理导入
ConfigurationClassParser-->>-ConfigurationClassParser:递归处理@Configuration
ConfigurationClassPostProcessor->>ConfigurationClassBeanDefinitionReader:loadBeanDefinitions(configClasses)加载bean定义
ConfigurationClassBeanDefinitionReader->>ConfigurationClassBeanDefinitionReader:loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator)加载配置类的bean定义
ConfigurationClassBeanDefinitionReader->>ConfigurationClassBeanDefinitionReader:registerBeanDefinitionForImportedConfigurationClass(configClass)注册导入的配置类的bean定义
ConfigurationClassBeanDefinitionReader->>DefaultListableBeanFactory:registerBeanDefinition(beanName,beanDefinition)在bean工厂中注册bean定义
ConfigurationClassBeanDefinitionReader->>ConfigurationClassBeanDefinitionReader:loadBeanDefinitionsFromRegistrars(registrars)从注册器中加载bean定义
ConfigurationClassBeanDefinitionReader->>MyImportBeanDefinitionRegistrar:registerBeanDefinitions(importingClassMetadata,registry)调用自定义的bean定义注册器
MyImportBeanDefinitionRegistrar->>DefaultListableBeanFactory:registerBeanDefinition(beanName,beanDefinition)在bean工厂中注册bean定义
七、源码分析
首先来看看启动类入口,上下文环境使用AnnotationConfigApplicationContext
(此类是使用Java注解来配置Spring容器的方式),构造参数我们给定了一个MyConfiguration
组件类,然后遍历并打印所有的bean定义名。
public class ImportApplication {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);
for (String beanDefinitionName : context.getBeanDefinitionNames()) {
System.out.println("beanName = " + beanDefinitionName);
}
}
}
在org.springframework.context.annotation.AnnotationConfigApplicationContext#AnnotationConfigApplicationContext
构造函数中,执行了三个步骤,我们重点关注refresh()
方法。
public AnnotationConfigApplicationContext(Class... componentClasses) {
this();
register(componentClasses);
refresh();
}
在org.springframework.context.support.AbstractApplicationContext#refresh
方法中我们重点关注一下finishBeanFactoryInitialization(beanFactory)
这方法会对实例化所有剩余非懒加载的单列Bean对象,其他方法不是本次源码阅读的重点暂时忽略。
@Override
public void refresh() throws BeansException, IllegalStateException {
// ... [代码部分省略以简化]
// 调用在上下文中注册为bean的工厂处理器
invokeBeanFactoryPostProcessors(beanFactory);
// ... [代码部分省略以简化]
}
在org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors
方法中,又委托了PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()
进行调用。
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// ... [代码部分省略以简化]
}
在org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors
方法中,首先调用了 BeanDefinitionRegistryPostProcessor
(这是 BeanFactoryPostProcessor
的子接口)。它专门用来在所有其他 bean 定义加载之前修改默认的 bean 定义。
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {
// ... [代码部分省略以简化]
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
// ... [代码部分省略以简化]
}
在org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors
方法中,循环调用了实现BeanDefinitionRegistryPostProcessor
接口中的postProcessBeanDefinitionRegistry(registry)
方法
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection