第三章 dubbo内核之ioc源码解析
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源码解析相关推荐
- Dubbo架构设计与源码解析(一) 架构设计
作者:黄金 一.架构演变 单应用架构 ----> 垂直架构 ----> 分布式架构 ----> 微服务架构 ----> 云原生架构 二.Dubbo总体架构 1.角色职能 • C ...
- Spring Bean的生命周期以及IOC源码解析
IOC源码这一块太多只能讲个大概吧,建议还是去买本Spring IOC源码解析的书来看比较好,我也是自己看源代码以及视频整理的笔记 Bean的生命周期大概可以分为四个阶段,具体的等会再说,先看看IOC ...
- Dubbo 实现原理与源码解析系列 —— 精品合集
摘要: 原创出处 http://www.iocoder.cn/Dubbo/good-collection/ 「芋道源码」欢迎转载,保留摘要,谢谢! 1.[芋艿]精尽 Dubbo 原理与源码专栏 2.[ ...
- Spring IOC源码解析笔记
小伙伴们,你们好,我是老寇 Spring最重要的概念就算IOC和AOP,本篇主要记录Spring IOC容器的相关知识,本文适合有spring相关基础并且想了解spring ioc的相关原理的人看 本 ...
- 聊聊Dubbo - Dubbo可扩展机制源码解析
2019独角兽企业重金招聘Python工程师标准>>> 摘要: 在Dubbo可扩展机制实战中,我们了解了Dubbo扩展机制的一些概念,初探了Dubbo中LoadBalance的实现, ...
- Activity与调用线(三):Activity生命周期源码解析
前言 很高兴遇见你~ 欢迎阅读我的文章. 关于Activity生命周期的文章,网络上真的很多,有很多的博客也都讲得相当不错,可见Activity的重要性是非常高的.事实上,我猜测每个android开发 ...
- linux内核radeon gpu源码解析3 —— Radeon初始化
解析DRM代码,以从底层介绍显卡驱动的初始化过程,显卡类型是AMD的radeon r600以后的系列显卡.基本的过程就是驱动载入,硬件初始化,设置硬件独立的模块(如内存管理器),设置显示(分辨率等). ...
- linux内核radeon gpu源码解析1 —— 什么是radeon
简介 Radeon(中文名称称为镭龙™)是一个英文产品的商标.Radeon是AMD公司出品的显示芯片的一种系列.俗称A卡. 全称一般写作:AMD Radeon HD xxxx ,例如台式机显卡型号:A ...
- Linux-4.20.8内核桥收包源码解析(一)----------sk_buff(详细)
作者:lwyang? 内核版本:Linux-4.20.8 网络子系统中用来存储数据的缓冲区叫做套接字缓存,简称SKB,可处理变长数据,尽量避免数据的复制. 每一个SKB都在设备中标识发送报文的目的或接 ...
最新文章
- 循环:for..in 与for...of 的区别
- Redis高级客户端Lettuce详解
- cad绘制椭圆的方法有几种_CAD新手入门教学:如何绘制矩形?
- 分布式存储与传统SAN、NAS的优、劣对比
- 《MANAGING THE DEVELOPMENT OF LARGE SOFTWARE SYSTEMS》总结
- UVA - 11806 Cheerleaders(组合数学+容斥原理)
- web页面在线编辑功能
- P3295 [SCOI2016]萌萌哒(DP+倍增)
- Source Server + Symbol Server
- 图注意力网络_EMNLP 2019开源论文:针对短文本分类的异质图注意力网络
- python-面向对象名词解析(类、实例、属性、方法、对象)
- HDU 6370(并查集)
- log4j配置日志文件log4j.appender.R.File相对路径方法
- 图像匹配滤波器 matlab,[转载]匹配滤波器的仿真验证(MATLAB)
- dell h330 不要做raid5 ,做raid0就可以了
- 动环监控系统发展趋势
- OpenHarmony代码下载编译流程记录
- php 判断华为手机,一招教你如何看穿华为手机的内存类型
- python爬虫scrapy爬取新闻标题及链接_18Python爬虫---CrawlSpider自动爬取新浪新闻网页标题和链接...
- 如何借势世界杯?看这10个运营活动就够了
热门文章
- Windows7 WIN 7 64位 环境编译6sv2.1版本的大气传输模型
- Specify compute hosts with SSDs
- ios8 UITableView section不显示
- websocket在.net4.5中实现的简单demo
- 使用 $.grep() 方法
- 一步一步学List Control控件的用法(第二步)----创建第一行
- 线段树、二叉堆以及离散化入门
- [C# 基础知识系列]专题五:当点击按钮时触发Click事件背后发生的事情
- Python之迭代器和生成器
- Spark Streaming Backpressure分析