【dubbo的IOC实现方法】

dubbo的IOC具体实现在:T injectExtension( T instance )方法中,该方法在3个地方被使用:

ExtensionLoader.getExtensionLoader(Protocol.class)
--new ExtensionLoader<T>(type)
----getAdaptiveExtension()
------createAdaptiveExtension()
/**1.为创建好的AdaptiveExtensionClass实例进行属性注入**/
--------injectExtension((T) getAdaptiveExtensionClass().newInstance()) /**2.为创建好的Extension实例进行属性注入**/
ExtensionLoader.getExtension("dubbo")
--createExtension("dubbo")
----injectExtension(instance);
/**3.为创建好的wrapperClass实例进行属性注入**/
----injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance)) //

injectExtension( T instance )源码】

injectExtension( T instance )方法的作用是通过instance对象的实例的setXxx(object)方法为instance的属性进行赋值,完成setter注入,类似Spring的ioc的经典注入方式。

详细步骤:

1.获取instance的setXxx方法,通过setXxx方法获取属性名称property和属性类型pt。

2.使用objectFactory创建属性property的对象实例object

3.执行method.invoke( instance, object ),注入property实例,即执行setXxx(object)方法

private T injectExtension(T instance) {
try {
if (objectFactory != null) {
for (Method method : instance.getClass().getMethods()) {
//成员变量的setXxx(T param)方法,例如:setName(String name)
if (method.getName().startsWith("set")
&& method.getParameterTypes().length == 1
&& Modifier.isPublic(method.getModifiers())) {
//获取参数param的类型的Class对象
Class<?> pt = method.getParameterTypes()[0];
try {
//通过方法名setXxx获取成员变量名xxx,例如setName-->name
String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";
//实例化参数object
Object object = objectFactory.getExtension(pt, property);
if (object != null) {
//执行instance实例对应的setXxx(object)方法,参数是object
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;
}

其中,比较重要的是

Object object = objectFactory.getExtension(pt, property);

这个方法,其中的ExtensionFactory objectFactory实例为 AdaptiveExtensionFactory实例,即

//伪代码
ExtensionFactory objectFactory = AdaptiveExtensionFactory实例

AdaptiveExtensionFactory的成员变量

factories = [SpringExtensionFactory实例, SpiExtensionFactory实例]

【 AdaptiveExtensionFactory 类源代码】

/**
* AdaptiveExtensionFactory
*
* @author william.liangf
*/
@Adaptive
public class AdaptiveExtensionFactory implements ExtensionFactory { private final List<ExtensionFactory> factories; public AdaptiveExtensionFactory() {
ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
List<ExtensionFactory> list = new ArrayList<ExtensionFactory>();
for (String name : loader.getSupportedExtensions()) {
list.add(loader.getExtension(name));
}
factories = Collections.unmodifiableList(list);
} /**
* 先调用SpiExtensionFactory来实例化
* 如果不行,再使用SpringExtensionFactory来实例化
**/
public <T> T getExtension(Class<T> type, String name) {
for (ExtensionFactory factory : factories) {
T extension = factory.getExtension(type, name);
if (extension != null) {
return extension;
}
}
return null;
} }

【SpiExtensionFactory源码】

/**
* SpiExtensionFactory
*
* @author william.liangf
*/
public class SpiExtensionFactory implements ExtensionFactory { public <T> T getExtension(Class<T> type, String name) {
//type是接口类型,且必须含有@SPI注解
if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {
ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(type);
//获取type的所有ExtensionClasses实现的key(例如:type是Protocol.class)
if (loader.getSupportedExtensions().size() > 0) {
//获取type的装饰类,如果有@Adaptive注解的类,则返回该类的实例,否则返回一个动态代理的实例(如:Protocol$Adaptive 的实例)
return loader.getAdaptiveExtension();
}
}
return null;
} }

结论:dubbo-spi相对于JDK-spi的一个好处,可以为SPI实现类注入SPI的装饰类或动态代理类。

【 SpringExtendsionFactory的源码 】

/**
* SpringExtensionFactory
*
* @author william.liangf
*/
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) {
//该context是否包含name的bean
if (context.containsBean(name)) {
//获取该name对应的bean,如果是懒加载或者多实例的bean,此时会实例化name对应的bean
Object bean = context.getBean(name);
//如果obj的类型是typ或者其子类,与instance相同
if (type.isInstance(bean)) {
return (T) bean;
}
}
}
return null;
} }

【参考文章】

https://www.cnblogs.com/java-zhao/p/7469786.html

04_dubbo_ioc的更多相关文章

随机推荐

  1. react-router的简单使用

    React Router是一个基于React之上的强大路由库,可以让你向应用中快速的添加视图和数据流,同时保持页面与URL间的同步. 1.安装: npm install --save react-ro ...

  2. paraview鼠标选择网格

    虽然可以根据ID选择网格,但是有时候需要选择可见面,直接鼠标比较方便,可以直接按一下键盘"S",这时候鼠标变成十字型,然后鼠标左键选择区域.

  3. Behind the scenes of the C# yield keyword(转)

    https://startbigthinksmall.wordpress.com/2008/06/09/behind-the-scenes-of-the-c-yield-keyword/ Behind ...

  4. 导出excel设置样式(Aspose.Cells)

    Aspose.Cells.Style style = xlBook.Styles[xlBook.Styles.Add()];style1.Pattern = Aspose.Cells.Backgrou ...

  5. 转 OGG 部署阶段常见问题

    序号 问题 解决方案1 "2019-04-13 20:23:55 ERROR OGG-00868 Oracle GoldenGate Capture for Oracle, e_db1.pr ...

  6. 转如何检查数据库是否处于一致性的状态 以及 如果在DG 库上备份,恢复成一个主库

    ##sample 0 不完全恢复之后,open resetlogs之前,怎么快速的检查数据库是否处于一致性的状态?https://blog.csdn.net/msdnchina/article/det ...

  7. Python爬虫:微博粉丝列表

    前言 本来打算做一个关于微博粉丝列表的爬虫,可以统计一下某个微博账号的粉丝里面,僵尸粉(水军)的数量,大V数量. 结果写完爬虫才发现,现在微博只给人看粉丝列表的前5页.......哈哈,好吧.挺无奈的 ...

  8. oracle--等待事件

    1. Buffer busy waits 从本质上讲,这个等待事件的产生仅说明了一个会话在等待一个Buffer(数据块),但是导致这个现象的原因却有很多种,常见的两种是:当一个会话试图修改一个数据块, ...

  9. vue-router vuex 用户信息管理

    实现原理: 每次进行路由跳转检测全局下用户信息状态是否存在 新建store.js文件 import Vue from 'vue': import Vuex from 'vuex': Vue.use(V ...

  10. 谈 Python 程序和 C 程序的整合 (转载)

    http://www.ibm.com/developerworks/cn/linux/l-cn-pythonandc/ 概览 Python 是一种用于快速开发软件的编程语言,它的语法比较简单,易于掌握 ...