写点什么

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)


用户头像

张健

关注

还未添加个人签名 2018.04.20 加入

还未添加个人简介

评论

发布
暂无评论
Spring中@Import的作用