Spring 中 @Import 的作用
发布于: 2021 年 01 月 12 日
先看源码:
/**
* 表示一个或更多个 component 类导入 -- 典型的 Configuration 类
*
* 提供和Spring xml 中 <import/>标签一样的功能,允许导入 @Configuration 类、ImportSelector 和
* ImportBeanDefinitionRegistrar 实现,以及标准的 component 类
*
* 导入配置类的bean 定义 应该通过使用 @Autowired 注解注入,要么这个Bean可以自己自动注入,或者配置类实例
* 声明这个bean可以被自动注入.
*
* 可以在类的等级上声明 或者作为一个注解元数据。
*
* 如果一个XML 或者其他 非配置类的Bean 定义资源需要被导入,可以使用 @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 {
/**
* {@link Configuration @Configuration}, {@link ImportSelector},
* {@link ImportBeanDefinitionRegistrar}, or regular component classes to import.
*/
Class<?>[] value();
}
复制代码
通过配置类解析器 ConfigurationClassParser,进行处理 @Import 注解 逻辑
class ConfigurationClassParser {
/**
*
* 递归收集所有声明@Import的值,不像大多数元注解那样,@Import 支持声明多个不同的值,通常从类的元注解
* 返回值的过程是不够用的。
* 举个例子,在配置类中直接声明 @Import,除了从 @Enable中获取元导入之外
* @param sourceClass the class to search
* @param imports the imports collected so far
* @param visited used to track visited classes to prevent infinite recursion
* @throws IOException if there is any problem reading metadata from the named class
*/
private void collectImports(SourceClass sourceClass, Set<SourceClass> imports, Set<SourceClass> visited)
throws IOException {
if (visited.add(sourceClass)) {
for (SourceClass annotation : sourceClass.getAnnotations()) {
String annName = annotation.getMetadata().getClassName();
if (!annName.equals(Import.class.getName())) {
collectImports(annotation, imports, visited);
}
}
imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));
}
}
/**
* 处理从@Import注解解析出来的类
*/
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(configClass);
try {
for (SourceClass candidate : importCandidates) {
// import 进来的类是 ImportSelector.class
if (candidate.isAssignable(ImportSelector.class)) {
// Candidate class is an ImportSelector -> delegate to it to determine imports
Class<?> candidateClass = candidate.loadClass();
// 实例化
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
// 回调Aware方法
ParserStrategyUtils.invokeAwareMethods(
selector, this.environment, this.resourceLoader, this.registry);
// 如果是延迟类的导入选择器
if (selector instanceof DeferredImportSelector) {
// 新建一个延迟处理类
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
}
else {
//
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
// 递归调用
processImports(configClass, currentSourceClass, importSourceClasses, false);
}
}
// import 进来的类是 ImportBeanDefinitionRegistrar.class
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 =
BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
ParserStrategyUtils.invokeAwareMethods(
registrar, 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));
}
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configClass.getMetadata().getClassName() + "]", ex);
}
finally {
this.importStack.pop();
}
}
}
}
复制代码
使用方式举例
@Import(AutoConfigurationImportSelector.class)
划线
评论
复制
发布于: 2021 年 01 月 12 日阅读数: 25
张健
关注
还未添加个人签名 2018.04.20 加入
还未添加个人简介
评论