dubbo的IOC具体实现在:T injectExtension(T instance)方法中。该方法只在三个地方被使用:

1 createAdaptiveExtension()
2 --injectExtension((T) getAdaptiveExtensionClass().newInstance()) //为创建好的AdaptiveExtensionClass实例进行属性注入
3
4 createExtension(String name)
5 --injectExtension(instance) //为创建好的Extension实例进行属性注入
6 --injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance)) //为创建好的wrapperClass实例进行属性注入

来看一下源码:

 1     /**
 2      * dubbo-IOC的核心
 3      */
 4     private T injectExtension(T instance) {
 5         try {
 6             if (objectFactory != null) {
 7                 for (Method method : instance.getClass().getMethods()) {
 8                     if (method.getName().startsWith("set") && method.getParameterTypes().length == 1
 9                         && Modifier.isPublic(method.getModifiers())) {//一个参数的public的setXXX(T param)方法.例如,setName(String name)
10                         Class<?> pt = method.getParameterTypes()[0];//参数param的类型T,eg.String
11                         try {
12                             String property = method.getName().length() > 3
13                                 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";//获取属性名XXX, eg.name
14                             Object object = objectFactory.getExtension(pt, property);//实例化参数
15                             if (object != null) {
16                                 //执行instance.method(object)方法,这里就是执行instance的setter方法,进行setter注入
17                                 method.invoke(instance, object);
18                             }
19                         } catch (Exception e) {
20                             logger.error("fail to inject via method " + method.getName() + " of interface "
21                                          + type.getName() + ": " + e.getMessage(),
22                                 e);
23                         }
24                     }
25                 }
26             }
27         } catch (Exception e) {
28             logger.error(e.getMessage(), e);
29         }
30         return instance;
31     }

整个方法的作用就是通过instance对象实例的setter方法为instance的属性赋值,完成setter注入,即IOC的最经典的注入方式。

详细步骤:

  • 获取instance的setter方法,通过setter方法获取属性名称property和属性类型pt(即paramType的简写)
  • 使用objectFactory创建一个property名称(类型为pt)的对象实例
  • 执行instance的setter方法,注入property实例

其中,比较重要的就是:Object object = objectFactory.getExtension(pt, property);这个方法。其中的objectFactory=AdaptiveExtensionFactory实例,其属性factories = [SpringExtensionFactory实例, SpiExtensionFactory实例]。

看一下源码:

 1     private final List<ExtensionFactory> factories;
 2
 3     public <T> T getExtension(Class<T> type, String name) {
 4         /**
 5          * 先调用SpiExtensionFactory来实例化;
 6          * 如果不行,再使用SpringExtensionFactory来实例化
 7          */
 8         for (ExtensionFactory factory : factories) {
 9             T extension = factory.getExtension(type, name);
10             if (extension != null) {
11                 return extension;
12             }
13         }
14         return null;
15     }

看一下SpiExtensionFactory的源码:

 1 public class SpiExtensionFactory implements ExtensionFactory {
 2     public <T> T getExtension(Class<T> type, String name) {
 3         if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {//type是接口且必须具有@SPI注解
 4             ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(type);
 5             if (loader.getSupportedExtensions().size() > 0) {//获取type的所有ExtensionClasses实现的key
 6                 return loader.getAdaptiveExtension();//获取type的装饰类,如果有@Adaptive注解的类,则返回该类的实例,否则返回一个动态代理类的实例(例如Protocol$Adpative的实例)
 7             }
 8         }
 9         return null;
10     }
11 }

从这里我们可以看出dubbo-SPI的另外一个好处:可以为SPI实现类注入SPI的装饰类或动态代理类。

看一下SpringExtensionFactory的源码:

 1 public class SpringExtensionFactory implements ExtensionFactory {
 2     private static final Set<ApplicationContext> contexts = new ConcurrentHashSet<ApplicationContext>();
 3
 4     public static void addApplicationContext(ApplicationContext context) {
 5         contexts.add(context);
 6     }
 7
 8     public static void removeApplicationContext(ApplicationContext context) {
 9         contexts.remove(context);
10     }
11
12     @SuppressWarnings("unchecked")
13     public <T> T getExtension(Class<T> type, String name) {
14         for (ApplicationContext context : contexts) {
15             if (context.containsBean(name)) {//该context是否包含name的bean
16                 Object bean = context.getBean(name);//获取name的bean,如果是懒加载或多例的bean,此时会实例化name的bean
17                 if (type.isInstance(bean)) {//如果obj的类型是type或其子类,与instanceof相同
18                     return (T) bean;
19                 }
20             }
21         }
22         return null;
23     }
24 }

至此,IOC就干完了。但是有一个遗留问题,ApplicationContext是什么时候加入到contexts中呢?当讲解ServiceBean的时候来说。

转载于:https://www.cnblogs.com/java-zhao/p/7469786.html

第三章 dubbo内核之ioc源码解析相关推荐

  1. Dubbo架构设计与源码解析(一) 架构设计

    作者:黄金 一.架构演变 单应用架构 ----> 垂直架构 ----> 分布式架构 ----> 微服务架构 ----> 云原生架构 二.Dubbo总体架构 1.角色职能 • C ...

  2. Spring Bean的生命周期以及IOC源码解析

    IOC源码这一块太多只能讲个大概吧,建议还是去买本Spring IOC源码解析的书来看比较好,我也是自己看源代码以及视频整理的笔记 Bean的生命周期大概可以分为四个阶段,具体的等会再说,先看看IOC ...

  3. Dubbo 实现原理与源码解析系列 —— 精品合集

    摘要: 原创出处 http://www.iocoder.cn/Dubbo/good-collection/ 「芋道源码」欢迎转载,保留摘要,谢谢! 1.[芋艿]精尽 Dubbo 原理与源码专栏 2.[ ...

  4. Spring IOC源码解析笔记

    小伙伴们,你们好,我是老寇 Spring最重要的概念就算IOC和AOP,本篇主要记录Spring IOC容器的相关知识,本文适合有spring相关基础并且想了解spring ioc的相关原理的人看 本 ...

  5. 聊聊Dubbo - Dubbo可扩展机制源码解析

    2019独角兽企业重金招聘Python工程师标准>>> 摘要: 在Dubbo可扩展机制实战中,我们了解了Dubbo扩展机制的一些概念,初探了Dubbo中LoadBalance的实现, ...

  6. Activity与调用线(三):Activity生命周期源码解析

    前言 很高兴遇见你~ 欢迎阅读我的文章. 关于Activity生命周期的文章,网络上真的很多,有很多的博客也都讲得相当不错,可见Activity的重要性是非常高的.事实上,我猜测每个android开发 ...

  7. linux内核radeon gpu源码解析3 —— Radeon初始化

    解析DRM代码,以从底层介绍显卡驱动的初始化过程,显卡类型是AMD的radeon r600以后的系列显卡.基本的过程就是驱动载入,硬件初始化,设置硬件独立的模块(如内存管理器),设置显示(分辨率等). ...

  8. linux内核radeon gpu源码解析1 —— 什么是radeon

    简介 Radeon(中文名称称为镭龙™)是一个英文产品的商标.Radeon是AMD公司出品的显示芯片的一种系列.俗称A卡. 全称一般写作:AMD Radeon HD xxxx ,例如台式机显卡型号:A ...

  9. Linux-4.20.8内核桥收包源码解析(一)----------sk_buff(详细)

    作者:lwyang? 内核版本:Linux-4.20.8 网络子系统中用来存储数据的缓冲区叫做套接字缓存,简称SKB,可处理变长数据,尽量避免数据的复制. 每一个SKB都在设备中标识发送报文的目的或接 ...

最新文章

  1. 循环:for..in 与for...of 的区别
  2. Redis高级客户端Lettuce详解
  3. cad绘制椭圆的方法有几种_CAD新手入门教学:如何绘制矩形?
  4. 分布式存储与传统SAN、NAS的优、劣对比
  5. 《MANAGING THE DEVELOPMENT OF LARGE SOFTWARE SYSTEMS》总结
  6. UVA - 11806 Cheerleaders(组合数学+容斥原理)
  7. web页面在线编辑功能
  8. P3295 [SCOI2016]萌萌哒(DP+倍增)
  9. Source Server + Symbol Server
  10. 图注意力网络_EMNLP 2019开源论文:针对短文本分类的异质图注意力网络
  11. python-面向对象名词解析(类、实例、属性、方法、对象)
  12. HDU 6370(并查集)
  13. log4j配置日志文件log4j.appender.R.File相对路径方法
  14. 图像匹配滤波器 matlab,[转载]匹配滤波器的仿真验证(MATLAB)
  15. dell h330 不要做raid5 ,做raid0就可以了
  16. 动环监控系统发展趋势
  17. OpenHarmony代码下载编译流程记录
  18. php 判断华为手机,一招教你如何看穿华为手机的内存类型
  19. python爬虫scrapy爬取新闻标题及链接_18Python爬虫---CrawlSpider自动爬取新浪新闻网页标题和链接...
  20. 如何借势世界杯?看这10个运营活动就够了

热门文章

  1. Windows7 WIN 7 64位 环境编译6sv2.1版本的大气传输模型
  2. Specify compute hosts with SSDs
  3. ios8 UITableView section不显示
  4. websocket在.net4.5中实现的简单demo
  5. 使用 $.grep() 方法
  6. 一步一步学List Control控件的用法(第二步)----创建第一行
  7. 线段树、二叉堆以及离散化入门
  8. [C# 基础知识系列]专题五:当点击按钮时触发Click事件背后发生的事情
  9. Python之迭代器和生成器
  10. Spark Streaming Backpressure分析