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. 《编写可维护的javascript》读书笔记(中)——编程实践

    上篇读书笔记系列之:<编写可维护的javascript>读书笔记(上) 上篇说的是编程风格,记录的都是最重要的点,不讲废话,写的比较简洁,而本篇将加入一些实例,因为那样比较容易说明问题. ...

  2. com.jcraft.jsch.JSchException: Auth fail

    背景 服务器信息: 服务器A:10.102.110.1 服务器B:10.102.110.2 需要从服务器A通过Sftp传输文件到服务器B. 应用项目中有一个功能,要通个关Sftp进行日志文件的传输,在 ...

  3. 初识thinkphp(4)

    这次内容是数据库的使用方法 因为在第一章讲过就是拿index这个文件写的数据库的访问,这次实验我使用文件是系统默认的首页 配置的内容也在那里有提过就不重发戳图了. 数据库按照手册上的建议建了3行的内容 ...

  4. BeagleBone Black教程之BeagleBone Black设备的连接

    BeagleBone Black教程之BeagleBone Black设备的连接 BeagleBone Black开发前需要准备的材料 经过上面的介绍,相信你已经对BeagleBone有了大致的了解, ...

  5. bzoj1205: [HNOI2005]星际贸易

    题目链接 bzoj1205: [HNOI2005]星际贸易 题解 辣鸡题面,毁我青春 辣鸡题面,毁我青 辣鸡题面,毁我 辣鸡题面,毁 第一问,背包dp 第二问 问题转化为在一个序列上经过好多点走到终点 ...

  6. BZOJ2924 : [Poi1998]Flat broken lines

    首先旋转坐标系 $x'=x-y$ $y'=-x-y$ 则对于一个点,它下一步可以往它左上角任意一个点连线. 根据Dilworth定理,答案=这个偏序集最长反链的长度. 设f[i]为到i点为止的最长反链 ...

  7. Codeforces Round #272 (Div. 2) D. Dreamoon and Sets 构造

    D. Dreamoon and Sets 题目连接: http://www.codeforces.com/contest/476/problem/D Description Dreamoon like ...

  8. 2013-2014 ACM-ICPC, NEERC, Southern Subregional Contest Problem F. Judging Time Prediction 优先队列

    Problem F. Judging Time Prediction 题目连接: http://www.codeforces.com/gym/100253 Description It is not ...

  9. 理解JVM模型

    概括 JVM运行时数据区可以划分为5部分,分别是:程序计数器.虚拟机栈.本地方法栈.堆.方法区 程序计数器(Program Counter Register) 相当于当前线程所执行字节码的行号指示器. ...

  10. Context Switching on the Cortex-M3

    http://coactionos.com/embedded%20design%20tips/2013/10/09/Tips-Context-Switching-on-the-Cortex-M3/ T ...