第三章 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"></ ...