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. 【转】SQL Server游标的使用

    在关系数据库中,我们对于查询的思考是面向集合的.而游标打破了这一规则,游标使得我们思考方式变为逐行进行.对于类C的开发人员来着,这样的思考方式会更加舒服. 正常面向集合的思维方式是: 而对于游标来说: ...

  2. mysql慢查询日志功能的使用

    作用:mysql慢查询日志可监控有效率问题的SQL .. 一.开启mysql慢查询日志功能 1.查看是否开启 未使用索引的SQL记录日志查询 mysql> show variables like ...

  3. 使用 IntraWeb (16) - 基本控件之 TIWList、TIWListbox、TIWComboBox、TIWOrderedListbox

    TIWList //列表; 它对应 Html 中的 OL.LI(某些选项下会用表格模拟); TIWListbox 和 TIWComboBox 则对应 Html 在的 Option TIWListbox ...

  4. ARM 汇编与C调用的若干问题(一般函数调用情况)

    ARM 汇编与C之间的函数调用需要符合ATPCS,建议函数的形参不超过4个,如果形参个数少于或等于4,则形参由R0,R1,R2,R3四个寄存器进行传递:若形参个数大于4,大于4的部分必须通过堆栈进行传 ...

  5. AutoFac简单入门

    AutoFac是.net程序下一个非常灵活易用,且功能强大的DI框架,本文这里简单的介绍一下使用方法. 安装: Install-Package Autofac 简单的示例: static void M ...

  6. How to add Leading Zeroes to a Number (Delphi Format)

    How to add Leading Zeroes to a Number (Delphi Format) Here's how convert (an integer) number to a st ...

  7. linux 内核升级2 转

    linux内核升级 一.Linux内核概览 Linux是一个一体化内核(monolithic kernel)系统. 设备驱动程序可以完全访问硬件. Linux内的设备驱动程序可以方便地以模块化(mod ...

  8. linux 内核升级 转

    inux 内核升级 2011-03-25 23:13:28 分类: LINUX 因要测试一些软件,需要2.6.30以上的内核,安装好CentOS 5.5,内核是2.6.18-194.el5.这次的升级 ...

  9. GO环境变量设置

    GOROOT就是go的安装路径在~/.bash_profile中添加下面语句: GOROOT=/usr/local/go export GOROOT 当然, 要执行go命令和go工具, 就要配置go的 ...

  10. Unity3d学习笔记记录

    1.发布到 ipad字体显示不出来,改变Position位置的Z轴为-1 2.发布打包有问题,记得用户权限有没有设置 3.ipad4分辨率:2048*1536 4.调整界面大小,尽量调整底下子对象位置 ...