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)@Documentedpublic @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 加入
还未添加个人简介











评论