今天看到一个神奇的用法, Spring可以通过@Import导入实现了ImportBeanDefinitionRegistrar接口的类来注册那个类.
ImportBeanDefinitionRegistrar接口是用来被实现以使Spring在处理Configuration的时候注册额外的bean. @Import注解可以引入一个Configuration类, 或ImportSelector实现类以根据特定条件导入合适的类. 其次就是可以引入实现了ImportBeanDefinitionRegistrar接口的类来直接注册类.

当然, 除了ImportBeanDefinitionRegistrar实现类, 还可以使用ClassPathBeanDefinitionScanner这个扫描器, 获取需要注册的bean. ClassPathBeanDefinitionScanner继承了ClassPathScanningCandidateComponentProvider, 其中有两个TypeFilter, includeFilters和excludeFilters, 可以用来过滤类.

比如以下即实现了ImportBeanDefinitionRegistrar接口:

class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {this.registerDefaultConfiguration(metadata, registry);this.registerFeignClients(metadata, registry);}
}

在registerFeignClients使用ClassPathScanningCandidateComponentProvider来过滤类, 注入包含了@FeignClient注解的类.

  public void registerFeignClients(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {ClassPathScanningCandidateComponentProvider scanner = this.getScanner();scanner.setResourceLoader(this.resourceLoader);Map<String, Object> attrs = metadata.getAnnotationAttributes(EnableFeignClients.class.getName());AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(FeignClient.class);Class<?>[] clients = attrs == null ? null : (Class[])((Class[])attrs.get("clients"));Object basePackages;if (clients != null && clients.length != 0) {final Set<String> clientClasses = new HashSet();basePackages = new HashSet();Class[] var9 = clients;int var10 = clients.length;for(int var11 = 0; var11 < var10; ++var11) {Class<?> clazz = var9[var11];((Set)basePackages).add(ClassUtils.getPackageName(clazz));clientClasses.add(clazz.getCanonicalName());}AbstractClassTestingTypeFilter filter = new AbstractClassTestingTypeFilter() {protected boolean match(ClassMetadata metadata) {String cleaned = metadata.getClassName().replaceAll("\\$", ".");return clientClasses.contains(cleaned);}};scanner.addIncludeFilter(new FeignClientsRegistrar.AllTypeFilter(Arrays.asList(filter, annotationTypeFilter)));} else {scanner.addIncludeFilter(annotationTypeFilter);basePackages = this.getBasePackages(metadata);}Iterator var17 = ((Set)basePackages).iterator();while(var17.hasNext()) {String basePackage = (String)var17.next();Set<BeanDefinition> candidateComponents = scanner.findCandidateComponents(basePackage);Iterator var21 = candidateComponents.iterator();while(var21.hasNext()) {BeanDefinition candidateComponent = (BeanDefinition)var21.next();if (candidateComponent instanceof AnnotatedBeanDefinition) {AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition)candidateComponent;AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();Assert.isTrue(annotationMetadata.isInterface(), "@FeignClient can only be specified on an interface");Map<String, Object> attributes = annotationMetadata.getAnnotationAttributes(FeignClient.class.getCanonicalName());String name = this.getClientName(attributes);this.registerClientConfiguration(registry, name, attributes.get("configuration"));this.registerFeignClient(registry, annotationMetadata, attributes);}}}}

转载于:https://www.cnblogs.com/helloz/p/11266358.html

Spring 通过@Import实现Bean的注册相关推荐

  1. Spring源码之Bean的注册(使用XML配置的方式)

    本文分析的Spring源码是5.2.2版本,使用Gradle进行管理. 一.Bean的注册,先来看通过XML配置Bean的方式 1.配置applicationContext.xml: <?xml ...

  2. Spring 使用@Import注入Bean的三种方式

    一.准备工作 1.导入spring-context依赖 <dependency><groupId>org.springframework</groupId>< ...

  3. Spring源码之Bean的注册(注解方式)

    1.创建AnnotationConfigApplicationContext AnnotationConfigApplicationContext context = new AnnotationCo ...

  4. spring系列-注解驱动原理及源码-bean组件注册

    目录 一.环境初始化 1.环境准备 二.bean的手动注入 1.xml方式注入bean 2.使用@Configuration&@Bean方式注入bean 三.自动扫描注册组件及bean 1.使 ...

  5. Spring源码解析-applicationContext.xml加载和bean的注册

    applicationContext文件加载和bean注册流程 ​ Spring对于从事Java开发的boy来说,再熟悉不过了,对于我们这个牛逼的框架的介绍就不在这里复述了,Spring这个大杂烩,怎 ...

  6. Spring系列第20篇:@Conditional通过条件来控制bean的注册

    面试阿里p7被问到的问题(当时我只知道第一个): @Conditional是做什么的? @Conditional多个条件是什么逻辑关系? 条件判断在什么时候执行? ConfigurationCondi ...

  7. Spring学习总结(6)——Spring之核心容器bean

    2019独角兽企业重金招聘Python工程师标准>>> 一.Bean的基础知识 1.在xml配置文件中,bean的标识(id 和 name) id:指定在benafactory中管理 ...

  8. 【Spring】BeanFactory解析bean详解

    为什么80%的码农都做不了架构师?>>>    本文是Spring源码分析中的一篇,来讲讲Spring框架中BeanFactory解析bean的过程,先来看一个在Spring中一个基 ...

  9. Spring源码剖析——Bean的配置与启动

    IOC介绍   相信大多数人在学习Spring时 IOC 和 Bean 算得上是最常听到的两个名词,IOC在学习Spring当中出现频率如此之高必然有其原因.如果我们做一个比喻的话,把Bean说成Sp ...

最新文章

  1. Cookie和Session的区别与联系
  2. LeetCode Majority Element
  3. linux之用户态和内核态
  4. WebNumericEdit
  5. TCP协议-握手与挥手
  6. 【算法系列之四】柱状图储水
  7. Spring源码分析-从源码看BeanFactory和FactoryBean的区别
  8. SSRF攻击实例解析
  9. educoder MongoDB 复制集 分片
  10. [Web 前端] 005 html 常用标签补充
  11. 宋健人口模型 matlab,一阶常微分方程模型-人口模型与预测
  12. jmeter分布式部署
  13. 贪心算法(greedy algorithm,又称贪婪算法)详解(附例题)
  14. java 文件比对(三)-- 使用 xmlUnit
  15. 年轻时代,噢,年轻时代
  16. 大话设计模式——解释器模式
  17. 基于权限特征和机器学习的Android恶意程序识别技术
  18. android 模拟物品移动
  19. linux看不到光模块,万兆光模块无法识别问题
  20. Druid 加载 Kafka 流数据的性能配置参数 TuningConfig

热门文章

  1. Java IO5:管道流、对象流
  2. 做网页前端遇到的一些问题
  3. 【网站开发】搭建一个属于自己的网站
  4. 知乎上-翻车的笔记本
  5. Cannot resolve field [product], input field list:[user, EXPR$0]
  6. ubuntu中用wine安装office2007
  7. 基于指数平滑对心电信号进行PQRST模拟(第二种方案)
  8. Tornado同步api和异步api混写一例
  9. 数据集哪些特征有多大的null列表
  10. Rosenbrock函数到底什么用