博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
04_dubbo_ioc
阅读量:5132 次
发布时间:2019-06-13

本文共 5608 字,大约阅读时间需要 18 分钟。

【dubbo的IOC实现方法】

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

ExtensionLoader.getExtensionLoader(Protocol.class)--new ExtensionLoader
(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 */@Adaptivepublic class AdaptiveExtensionFactory implements ExtensionFactory {    private final List
factories; public AdaptiveExtensionFactory() { ExtensionLoader
loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class); List
list = new ArrayList
(); for (String name : loader.getSupportedExtensions()) { list.add(loader.getExtension(name)); } factories = Collections.unmodifiableList(list); } /** * 先调用SpiExtensionFactory来实例化 * 如果不行,再使用SpringExtensionFactory来实例化 **/ public
T getExtension(Class
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 getExtension(Class
type, String name) { //type是接口类型,且必须含有@SPI注解 if (type.isInterface() && type.isAnnotationPresent(SPI.class)) { ExtensionLoader
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
contexts = new ConcurrentHashSet
(); public static void addApplicationContext(ApplicationContext context) { contexts.add(context); } public static void removeApplicationContext(ApplicationContext context) { contexts.remove(context); } @SuppressWarnings("unchecked") public
T getExtension(Class
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

转载于:https://www.cnblogs.com/HigginCui/p/9610021.html

你可能感兴趣的文章
2017年BackBox5和Ubuntu16.04.1国内更新源
查看>>
NASA: Seeing Jupiter(注视木星)
查看>>
软件开发基本原则(一)—— 策略和因素 (转)
查看>>
Linux 查看系统所有用户
查看>>
实验三——for 语句及分支结构else-if
查看>>
国家哲学社会科学文献中心
查看>>
把一些表单属性封装一个JSON
查看>>
module
查看>>
Linux平台下卸载MySQL的方法
查看>>
ubuntu下安装Docker
查看>>
CF1152 F. Neko Rules the Catniverse (dp)
查看>>
全国行政区域数据库
查看>>
8_19 比赛总结 [暑假集训]
查看>>
GET与POST的区别
查看>>
花容月貌
查看>>
Spring Roo 之 Mysql 连接
查看>>
Spring_Mybatis整合实现CRUD操作
查看>>
Android学习第六天---seekbar
查看>>
C++ lambda
查看>>
div中显示页面
查看>>