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源码解析的更多相关文章

  1. 第四章 dubbo内核之aop源码解析

    ExtensionLoader<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class); final P ...

  2. Spring系列(三):Spring IoC源码解析

    一.Spring容器类继承图 二.容器前期准备 IoC源码解析入口: /** * @desc: ioc原理解析 启动 * @author: toby * @date: 2019/7/22 22:20 ...

  3. Spring IoC源码解析之invokeBeanFactoryPostProcessors

    一.Bean工厂的后置处理器 Bean工厂的后置处理器:BeanFactoryPostProcessor(触发时机:bean定义注册之后bean实例化之前)和BeanDefinitionRegistr ...

  4. Spring IoC源码解析之getBean

    一.实例化所有的非懒加载的单实例Bean 从org.springframework.context.support.AbstractApplicationContext#refresh方法开发,进入到 ...

  5. Spring IoC源码解析——Bean的创建和初始化

    Spring介绍 Spring(http://spring.io/)是一个轻量级的Java 开发框架,同时也是轻量级的IoC和AOP的容器框架,主要是针对JavaBean的生命周期进行管理的轻量级容器 ...

  6. Spring IOC 源码解析(持续)

    如何查看源码 Spring源码下载https://github.com/spring-projects/spring-framework/tags?after=v3.1.0.RC1 eclipse关联 ...

  7. spring ioc 源码解析

    什么是ioc? 通俗的解释是:(spring)框架中,完成对象的创建和注入的容器. springIOC体系结构: spring IOC的创建是典型的工厂模式,这一系列的bean工厂如上所示. 其核心是 ...

  8. 第零章 dubbo源码解析目录

    第一章 第一个dubbo项目 第二章  dubbo内核之spi源码解析 2.1  jdk-spi的实现原理 2.2 dubbo-spi源码解析 第三章 dubbo内核之ioc源码解析 第四章 dubb ...

  9. 5.2 dubbo-compiler源码解析

    ExtensionLoader<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class); final P ...

随机推荐

  1. python集合相关操作

    集合相关操作 集合是一个无序的,不重复的数据组合,它有着两个主要作用:去重以及关系测试. 去重指的是当把一个列表变成了集合,其中重复的内容就自动的被去掉了 关系测试指的是,测试两组数据之间的交集.差集 ...

  2. Django模版语言inclusion_tag的用法。

        inclusion_tag.它多用于一个HTML片段的.例如我写的一个BBS项目中. 一个博主的主页面的左侧栏和查看博主某篇文章的页面的左栅栏的一样的.为了不用重复写同样的代码.且提高页面的扩 ...

  3. hiho1270 建造基地([Offer收割]编程练习赛1)

    题目意思很简单, 一道类似于背包的问题,问恰好超过背包容量的最小取值.并且需要计算n次,每计算一次都要将所有的物品的价值w[i] /= t,最后输出背包n次的总使用容量. 如果无法实现输出”No An ...

  4. zoj 3662 第37届ACM/ICPC长春赛区H题(DP)

    题目:给出K个数,使得这K个数的和为N,LCM为M,问有多少种 f[i][j][k]表示选i个数,总和为j,最小公倍数为k memery卡的比较紧,注意不要开太大,按照题目数据开 这种类型的dp也是第 ...

  5. UVALive 6909 Kevin's Problem 数学排列组合

    Kevin's Problem 题目连接: https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid ...

  6. MikroTik RouterOS使用U盘安装提示FATAL ERROR: no CD-ROM found Press ENTER to reboot的问题解决

    1.首先说明这个ROS是不能使用U盘安装的,无论你怎么修改都无法实现 2.还是老老实实的刻录iso关盘,或者挂载硬盘到虚拟机上进行安装.又或者使用netinstall进行安装. 3.别去找国外的方法, ...

  7. 从Redis的数据丢失说起(转)

    碰到一个悲催的事情:一台Redis服务器,4核,16G内存且没有任何硬件上的问题.持续高压运行了大约3个月,保存了大约14G的数据,设置了比较完备的Save参数.而就是这台主机,在一次重起之后,丢失了 ...

  8. java高新技术

    一.静态导入: import static语句导入一个类中的某个静态方法或所有方法: 例子: 1.import static java.lang.Math.max; 只是导入了Math类中的max方法 ...

  9. Revit API判断是不是柱族模板

    OwnerFamily即族模板.获取类别的方法:Document.Settings.Categories.get_Item(BuiltInCategory.OST_Columns); //判断是不是柱 ...

  10. Sqlite3+EF6踩的坑

    摘要 最近在用winform,有些数据需要本地存储,所以想到了使用sqlite这个文件数据库.在使用Nuget安装sqlite的时候,发现会将Ef也安装上了,所以想着使用EF进行数据的操作吧,所以这就 ...