首先看下@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

欢迎扫码加关注:

@mapperscan注解_Spring的@Import注解详解相关推荐

  1. async spring 默认线程池_Spring boot注解@Async线程池实例详解

    这篇文章主要介绍了Spring boot注解@Async线程池实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 从Spring3开始提供了@A ...

  2. Spring基于注解TestContext 测试框架使用详解

    原创整理不易,转载请注明出处:Spring基于注解TestContext 测试框架使用详解 代码下载地址:http://www.zuidaima.com/share/1775574182939648. ...

  3. Spring高级之注解@Import注解、ImportSelector、ImportBeanDefinitionRegistrar详解(超详细)

    定义/作用 @Import注解只能作用在类上,一种使用场景是在spring注解驱动开发环境下与配置类配合使用的,其作用是引用其他配置类.使得我们可以和早起的基于XML配置文件开发那样.使用不同的配置类 ...

  4. SpringAOP描述及实现_AspectJ详解_基于注解的AOP实现_SpringJdbcTemplate详解

    AOP AOP特点: 面向切面编程, 利用AOP对业务逻辑的各个部分进行抽取公共代码, 降低耦合度, 提高代码重用性, 同时提高开发效率. 采取横向抽取, 取代传统纵向继承体系重复性代码 解决事务管理 ...

  5. Java注解编译期处理AbstractProcessor详解

    文章目录 概述 注解处理器 注解处理流程 AbstractProcessor getSupportedOptions() getSupportedAnnotationTypes getSupporte ...

  6. JAVA中Explain注解用法,mysql之explain详解(分析索引最佳使用)

    mysql之explain详解(分析索引最佳使用) mysql explain用于分析sql 语句的执行及数据库索引的使用.本文将致力于帮助大家充分理解explain所返回的各项参数,从而使大家快速掌 ...

  7. Restful API注解之@PathVariable和@JsonView详解

    **对于restful API的使用可以查看我之前的文章SpringMVC开发restful API查询请求 本文将在restful API的基础上介绍@PathVariable和@JsonView注 ...

  8. python import io_详解Python IO编程

    文件读写 读文件 try: # windows下utf8 f = open('./README.md', 'r', encoding='utf8', errors='ignore') print(f. ...

  9. java集成redis集群_spring集成redis cluster详解

    客户端采用最新的jedis 2.7 1.maven依赖: redis.clients jedis 2.7.3 2.增加spring 配置 classpath:connect-redis.propert ...

最新文章

  1. IoU、GIoU、DIoU、CIoU损失函数的那点事儿
  2. spring框架学习(一)入门
  3. enum python_enum:python实现枚举也很优雅
  4. C++Odd Even Sort奇偶排序的实现算法(附完整源码)
  5. 常见服务器解析漏洞(IIS,Nginx,Apache)
  6. 《Java编码指南:编写安全可靠程序的75条建议》—— 指南19:对细粒度的安全定义自定义安全权限...
  7. 今日恐慌与贪婪指数为65 等级转为贪婪
  8. 【渝粤题库】陕西师范大学800012 区域经济学
  9. php为图片平铺文字水印
  10. 如何自定义Chromecast的背景以显示个性化图片,新闻等
  11. html打印自定义页头,CSS实现打印网页自定义页眉页脚
  12. Nachos操作系统synch(lab3)
  13. 流量变现的10种方式
  14. 世界的下一个主宰——人工智能
  15. oracle批量备份表的存储过程
  16. 让AI帮你玩游戏(一) 基于目标检测用几个样本帮你实现在魔兽世界中钓鱼(群已满)
  17. linux 声音网络推送,这是一篇有声音的推送
  18. 引领半开放主动降噪新技术,华为全新无线蓝牙耳机FreeBuds 4发布
  19. 数据结构(c语言版严蔚敏_吴伟民)读书笔记 第一章
  20. matlab保存和载入数据,matlab数据的导入导出-总结篇

热门文章

  1. derby数据库操作比较难理解的错误及解决方法大全
  2. linux的常用操作——open函数
  3. hadoop 重新格式化 NameNode
  4. python-非负矩阵分解-NMF
  5. 【剑指offer】面试题46. 把数字翻译成字符串(java)
  6. 华为p10plus能用鸿蒙吗,华为P10/P10 Plus对比评测:自家兄弟大对决
  7. 计算机组成说明,计算机组成与系统结构考试说明.ppt
  8. pytorch每次迭代训练前都重新对数据集进行采样形成平衡数据集
  9. Opencv——基于索引表的图像细化
  10. 汇编语言 test 和 cmp 区别