04_dubbo_ioc

【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

原文地址:https://www.cnblogs.com/HigginCui/p/9610021.html