首先看下@Import的javadoc文档:

Provides functionality equivalent to the <import/> element in Spring XML. Allows for importing @Configuration classes, ImportSelector and ImportBeanDefinitionRegistrar implementations, as well as regular component classes (as of 4.2; analogous to AnnotationConfigApplicationContext.register).
@Bean definitions declared in imported @Configuration classes should be accessed by using @Autowired injection. Either the bean itself can be autowired, or the configuration class instance declaring the bean can be autowired. The latter approach allows for explicit, IDE-friendly navigation between @Configuration class methods.
May be declared at the class level or as a meta-annotation.

简单翻译一下,这里面说了3个点:

(1)@Import就是用来向容器中导入bean的,导入的方式有三种:导入@Configuration、导入ImportSelector、导入ImportBeanDefinitionRegistrar。

(2)被@Import的类是被加载到了Spring容器当中,因此无论是类本身还是类里面用@Bean注解定义的bean都可以被@Autowired注入。

(3)@Import可以加在类上面,也可以作为元注解加在注解上面

下面就来分别举例说明下。

1.导入@Configuration举例

//这是个普通的类
public class Service1 {public Service1(){System.out.println("Service1");}
}
//这是个配置类
@Configuration
public class DemoConfig {@Beanpublic Service2 service2(){return new Service2();}
}
@SpringBootApplication
//这样可以导入Service1和Service2这两个Bean
@Import({Service1.class, DemoConfig.class})
public class ImportDemoApplication {public static void main(String[] args) {SpringApplication.run(ImportDemoApplication.class, args);}
}

2.导入ImportSelector举例

public class DemoImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {//这里返回bean的完整的名字return new String[]{"com.github.xjs.importdemo.service.Service3"};}
}
@SpringBootApplication
//这样就可以导入Service3这个bean
@Import({DemoImportSelector.class})
public class ImportDemoApplication {public static void main(String[] args) {SpringApplication.run(ImportDemoApplication.class, args);}
}

3.导入ImportBeanDefinitionRegistrar举例

public class DemoRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {//可以直接向容器注册beanGenericBeanDefinition bd = new GenericBeanDefinition();bd.setBeanClass(Service4.class);registry.registerBeanDefinition("service4", bd);}
}
@SpringBootApplication
//这样就可以导入Service4这个bean
@Import({DemoRegistrar.class})
public class ImportDemoApplication {public static void main(String[] args) {SpringApplication.run(ImportDemoApplication.class, args);}
}

4.@Import作为元注解使用举例

因为@Import可以作为元注解使用,因此可以用这个特性来做组件扫描,比如:

//首先定义一个用于扫描的注解,上面添加@Import元注解:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Import({DemoImportSelector.class})
public @interface DemoScan {/*** 要扫描的根路径* */String basePackage() default "";
}

然后在启动类或者配置类上添加这个注解:

@SpringBootApplication
//首先添加这个注解
@DemoScan(basePackage="com.github.xjs")
@Import({DemoImportSelector.class, DemoRegistrar.class})
public class ImportDemoApplication {public static void main(String[] args) {SpringApplication.run(ImportDemoApplication.class, args);}
}

无论是ImportSelector还是ImportBeanDefinitionRegistrar在回调中都可以使用AnnotationMetadata获取@DemoScan里面的属性:

public class DemoImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {//读取DemoScan的属性AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(DemoScan.class.getName()));String basePackage = annoAttrs.getString("basePackage");System.out.println("basePackage:"+basePackage);return new String[]{"com.github.xjs.importdemo.service.Service3"};}
}

拿到了要扫描的路径如何去扫描可以参考上一篇如何去扫描Mapper接口的,在Spring的源码中有大量的这种用法,比如:ServletComponentScan与ServletComponentScanRegistrar、MapperScan与MapperScannerRegistrar等等。

5.@Import解析的源码

// org.springframework.context.annotation.ConfigurationClassParser:
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,Collection<SourceClass> importCandidates, boolean checkForCircularImports) {...for (SourceClass candidate : importCandidates) {if (candidate.isAssignable(ImportSelector.class)) {// Candidate class is an ImportSelector -> delegate to it to determine importsClass<?> candidateClass = candidate.loadClass();ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);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);}}else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {// Candidate class is an ImportBeanDefinitionRegistrar ->// delegate to it to register additional bean definitionsClass<?> 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 classthis.importStack.registerImport(currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());processConfigurationClass(candidate.asConfigClass(configClass));}}...
}
}

完整的源码下载:

https://github.com/xjs1919/enumdemo 下的 import-demo

欢迎扫码加关注:

ideal如何快速导入import_Spring的@Import注解详解相关推荐

  1. 【Spring】@Import注解详解

    简述 @Import注解import的是其他地方定义的Bean,将松散的Bean集合在一起. 既可以引入普通类作为Bean,又可以引入标记了@Configuration类中的所有Bean. 1. 引入 ...

  2. @Import注解详解

    @Import注解提供了三种用法 1.@Import一个普通类 spring会将该类加载到spring容器中 2.@Import一个类,该类实现了ImportBeanDefinitionRegistr ...

  3. @mapperscan注解_Spring的@Import注解详解

    首先看下@Import的javadoc文档: Provides functionality equivalent to the <import/> element in Spring XM ...

  4. php 如何封装类库,ThinkPHP里的import方法用于类库导入的封装实现实例详解

    ThinkPHP里的import方法用于类库导入的封装实现实例详解 分类:PHP_Python| 发布:佚名| 查看: | 发表时间:2014/7/1 import方法是ThinkPHP框架用于类库导 ...

  5. springioc注解详解

    springioc注解详解 文章目录 springioc注解详解 *简略核心解释 一.springioc是什么? 二.使用步骤 1.使用注解的方式注册bean到IOC容器中 2.使用@AutoWire ...

  6. JDBC学习笔记01【JDBC快速入门、JDBC各个类详解、JDBC之CRUD练习】

    黑马程序员-JDBC文档(腾讯微云)JDBC笔记.pdf:https://share.weiyun.com/Kxy7LmRm JDBC学习笔记01[JDBC快速入门.JDBC各个类详解.JDBC之CR ...

  7. Spring零配置之@Configuration注解详解

    转载自 Spring零配置之@Configuration注解详解 @Configuration介绍 Spring3.0之前要使用Spring必须要有一个xml配置文件,这也是Spring的核心文件,而 ...

  8. Spring Boot注解详解

    文章目录 使用注解的优势 注解详解(配备了完善的释义) 注解列表如下 JPA注解 springMVC相关注解 全局异常处理 项目中具体配置解析和使用环境 使用注解的优势 采用纯java代码,不在需要配 ...

  9. 【SpringBoot 】SpringBoot注解详解

    [SpringBoot ]SpringBoot注解详解 一.注解(annotations)列表  @SpringBootApplication:包含了@ComponentScan.@Configura ...

最新文章

  1. ASA IPSEC ***配置
  2. 一块网卡绑定多个ip
  3. c语言指针字符串逆序存放,C语言指针实现字符串的反转
  4. 2021 icme_重磅 | 2021年U.S. News 全美院校排名发布,疫情之下,排名大洗牌?!
  5. 网络编程知识预备(5) ——libcurl库简介及其编程访问百度首页
  6. [数据结构]链表中销毁和清空的区别
  7. LeetCode 211. 添加与搜索单词 - 数据结构设计(Trie树)
  8. Java面试通关要点汇总集答案(七)——equals 与 == 的区别 List 和 Set 区别
  9. mycat分表之ER表分片、范围分片、取模分片、日期分片、全局表等
  10. CACTI 仙人掌监控平台
  11. yolov5鱼苗检测计数:从数据标注到训练
  12. 《51单片机应用开发从入门到精通》——1.3 Keil uVision2集成开发环境
  13. Java开发从零开始!java游戏服务器开发教程
  14. rust炼油机怎么搞_rust挖油机在哪个位置 | 手游网游页游攻略大全
  15. 51nod 1108.距离之和最小 V2 - 曼哈顿距离
  16. 千万级规模高性能、高并发的网络架构经验分享
  17. JZOJ 5207【GDOI2018模拟7.7】暴力大神hxx
  18. 我的编程之路:从好玩到玩好
  19. [再寄小读者之数学篇](2014-11-20 计算二重积分)
  20. node中全局对象一 --- __dirname和__filename

热门文章

  1. 【分享】Vue 资源典藏(UI组件、开发框架、服务端、辅助工具、应用实例、Demo示例)...
  2. bootstrap layui 两种分页的实现
  3. Linux线程-互斥锁pthread_mutex_t
  4. Java内存溢出详解
  5. 【集合框架】JDK1.8源码分析之IdentityHashMap(四)
  6. PyQt的Layout的比例化分块。
  7. oracle监听器启动错误-TNS-12546: TNS:permission denied
  8. Linux硬盘安装_ubuntu
  9. HTML5 特性检测:Canvas(画布)
  10. python3 nmap 函数简介