第三章 dubbo内核之ioc源码解析
dubbo的IOC具体实现在:T injectExtension(T instance)方法中。该方法只在三个地方被使用:
createAdaptiveExtension()
--injectExtension((T) getAdaptiveExtensionClass().newInstance()) //为创建好的AdaptiveExtensionClass实例进行属性注入 createExtension(String name)
--injectExtension(instance) //为创建好的Extension实例进行属性注入
--injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance)) //为创建好的wrapperClass实例进行属性注入
来看一下源码:
/**
* dubbo-IOC的核心
*/
private T injectExtension(T instance) {
try {
if (objectFactory != null) {
for (Method method : instance.getClass().getMethods()) {
if (method.getName().startsWith("set") && method.getParameterTypes().length == 1
&& Modifier.isPublic(method.getModifiers())) {//一个参数的public的setXXX(T param)方法.例如,setName(String name)
Class<?> pt = method.getParameterTypes()[0];//参数param的类型T,eg.String
try {
String property = method.getName().length() > 3
? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";//获取属性名XXX, eg.name
Object object = objectFactory.getExtension(pt, property);//实例化参数
if (object != null) {
//执行instance.method(object)方法,这里就是执行instance的setter方法,进行setter注入
method.invoke(instance, object);
}
} catch (Exception e) {
logger.error("fail to inject via method " + method.getName() + " of interface "
+ type.getName() + ": " + e.getMessage(),
e);
}
}
}
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return instance;
}
整个方法的作用就是通过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实例]。
看一下源码:
     private final List<ExtensionFactory> factories;
     public <T> T getExtension(Class<T> type, String name) {
         /**
          * 先调用SpiExtensionFactory来实例化;
          * 如果不行,再使用SpringExtensionFactory来实例化
          */
         for (ExtensionFactory factory : factories) {
             T extension = factory.getExtension(type, name);
             if (extension != null) {
                 return extension;
             }
         }
         return null;
     }
看一下SpiExtensionFactory的源码:
 public class SpiExtensionFactory implements ExtensionFactory {
     public <T> T getExtension(Class<T> type, String name) {
         if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {//type是接口且必须具有@SPI注解
             ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(type);
             if (loader.getSupportedExtensions().size() > 0) {//获取type的所有ExtensionClasses实现的key
                 return loader.getAdaptiveExtension();//获取type的装饰类,如果有@Adaptive注解的类,则返回该类的实例,否则返回一个动态代理类的实例(例如Protocol$Adpative的实例)
             }
         }
         return null;
     }
 }
从这里我们可以看出dubbo-SPI的另外一个好处:可以为SPI实现类注入SPI的装饰类或动态代理类。
看一下SpringExtensionFactory的源码:
 public class SpringExtensionFactory implements ExtensionFactory {
     private static final Set<ApplicationContext> contexts = new ConcurrentHashSet<ApplicationContext>();
     public static void addApplicationContext(ApplicationContext context) {
         contexts.add(context);
     }
     public static void removeApplicationContext(ApplicationContext context) {
         contexts.remove(context);
     }
     @SuppressWarnings("unchecked")
     public <T> T getExtension(Class<T> type, String name) {
         for (ApplicationContext context : contexts) {
             if (context.containsBean(name)) {//该context是否包含name的bean
                 Object bean = context.getBean(name);//获取name的bean,如果是懒加载或多例的bean,此时会实例化name的bean
                 if (type.isInstance(bean)) {//如果obj的类型是type或其子类,与instanceof相同
                     return (T) bean;
                 }
             }
         }
         return null;
     }
 }
至此,IOC就干完了。但是有一个遗留问题,ApplicationContext是什么时候加入到contexts中呢?当讲解ServiceBean的时候来说。
第三章 dubbo内核之ioc源码解析的更多相关文章
- 第四章  dubbo内核之aop源码解析
		
ExtensionLoader<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class); final P ...
 - Spring系列(三):Spring IoC源码解析
		
一.Spring容器类继承图 二.容器前期准备 IoC源码解析入口: /** * @desc: ioc原理解析 启动 * @author: toby * @date: 2019/7/22 22:20 ...
 - Spring IoC源码解析之invokeBeanFactoryPostProcessors
		
一.Bean工厂的后置处理器 Bean工厂的后置处理器:BeanFactoryPostProcessor(触发时机:bean定义注册之后bean实例化之前)和BeanDefinitionRegistr ...
 - Spring IoC源码解析之getBean
		
一.实例化所有的非懒加载的单实例Bean 从org.springframework.context.support.AbstractApplicationContext#refresh方法开发,进入到 ...
 - Spring IoC源码解析——Bean的创建和初始化
		
Spring介绍 Spring(http://spring.io/)是一个轻量级的Java 开发框架,同时也是轻量级的IoC和AOP的容器框架,主要是针对JavaBean的生命周期进行管理的轻量级容器 ...
 - Spring IOC 源码解析(持续)
		
如何查看源码 Spring源码下载https://github.com/spring-projects/spring-framework/tags?after=v3.1.0.RC1 eclipse关联 ...
 - spring ioc   源码解析
		
什么是ioc? 通俗的解释是:(spring)框架中,完成对象的创建和注入的容器. springIOC体系结构: spring IOC的创建是典型的工厂模式,这一系列的bean工厂如上所示. 其核心是 ...
 - 第零章 dubbo源码解析目录
		
第一章 第一个dubbo项目 第二章 dubbo内核之spi源码解析 2.1 jdk-spi的实现原理 2.2 dubbo-spi源码解析 第三章 dubbo内核之ioc源码解析 第四章 dubb ...
 - 5.2  dubbo-compiler源码解析
		
ExtensionLoader<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class); final P ...
 
随机推荐
- play framework系列之maven 构建
			
一,文章内容 1,Play framwwork 的好处就是构建java 项目简单快速.经过下边几步即可完成. play new testSimpleMvn 选择2 java 项目即可. 然后进入到 t ...
 - 吴恩达-coursera-机器学习-week10
			
十七.大规模机器学习(Large Scale Machine Learning) 17.1 大型数据集的学习 17.2 随机梯度下降法 17.3 小批量梯度下降 17.4 随机梯度下降收敛 17.5 ...
 - URAL 1970 J - 皇后像廣場 dfs
			
J - 皇后像廣場 题目连接: http://acm.hust.edu.cn/vjudge/contest/123332#problem/J Description Vova was walking ...
 - SlickMaster.NET 开源表单设计器快速使用指南
			
前言:在企业数据处理过程中,经常需要通过定制表单来输入业务数据.由于涉及的数据比较离散,并不同于ERP系统的紧密关联数据.假如由开发人员每个增加页面,工作量会比较大,后期后期的维护很升级也耗费时间和精 ...
 - CentOS 安装 Python3
			
CentOS 7 默认安装 python 2.7.5 如图: 开始安装Python 3.6.3 1.下载Python3.6.3包: 拉到最下面,找到对应的包.复制下载链接地址: wget https ...
 - STM32 F4 General-purpose Timers for Periodic Interrupts
			
STM32 F4 General-purpose Timers for Periodic Interrupts
 - read(10, "NTP0 13690\n", 64) 数据库登录缓慢
			
初步怀疑:下面两个參数引起: SQL> conn / as sysdba Connected. SQL> show parameter lock NAME ---------------- ...
 - Linux内存管理学习3 —— head.S中的段页表的建立
			
作者 彭东林 pengdonglin137@163.com 平台 TQ2440 Qemu+vexpress-ca9 Linux-4.10.17 正文 继续分析head.S: ldr r13, =__m ...
 - lufylegend:动画
			
1.动画1 <script type="text/javascript"> var loader,anime,layer; //初始化画布 init(200, &quo ...
 - 【转载】ArcEngine ITable 与System.DataTable相互转换
			
/// <summary> /// 打开dbf表 /// </summary> /// <param name="pathName"></ ...