dubbo扩展点的IOC

spring是如何获得容器中管理的类的

拿到applicationContext,就可以调用getBean方法来获得Spring的bean对象了

public class SpringContextUtil implements ApplicationContextAware {  
    // Spring应用上下文环境  
    private static ApplicationContext applicationContext;  
    /** 
     * 实现ApplicationContextAware接口的回调方法,设置上下文环境 
     *  
     * @param applicationContext 
     */  
    public void setApplicationContext(ApplicationContext applicationContext) {  
        SpringContextUtil.applicationContext = applicationContext;  
    }  
    /** 
     * @return ApplicationContext 
     */  
    public static ApplicationContext getApplicationContext() {  
        return applicationContext;  
    }  
    /** 
     * 获取对象 
     *  
     * @param name 
     * @return Object
     * @throws BeansException 
     */  
    public static Object getBean(String name) throws BeansException {  
        return applicationContext.getBean(name);  
    }  
}

dubbo扩展点的IOC

前文中,大致有提到一些有关IOC

  • 第一点 在讲解ExtensionLoader源码的构造函数的时候,我们说过,每一个ExtensionLoader实例都有一个 objectFactory 属性,他是实现Ioc的关键;
  • 第二点 相比较于JDK的SPI机制,dubbo的SPI机制支持扩展通过setter的方式来注入其他扩展点。
  • 第三点 在调用ExtensionLoader的getExtension方法时,在获取了相应的class并创建了instance之后,通过injectExtension(intance)方法来通过setter的方式来注入其他扩展点。
  • 第四点 loadFile函数解析SPI配置时,假如这个类带@Adaptive注解,缓存到cachedAdaptiveClass。

如何实现IOC -> ExtensionLoader的injectExtension方法源码

关键说明,

  1. 获取instance的所有方法,并解析以set方法开头的方法,例如setXxyy(Xxyy xxyy)。
  2. 拿到set方法的入参类型Xxyy、属性名xxyy。
  3. 执行objectFactory.getExtension(pt, property)拿到Xxyy对应的实例。
  4. 通过反射执行set方法,注入Xxyy对象。
    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())) {
                        Class<?> pt = method.getParameterTypes()[0];
                        try {
                            String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";
                            Object object = objectFactory.getExtension(pt, property);
                            if (object != null) {
                                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中,实现自动装配(IOC)。下面我们来看一下 objectFactory.getExtension(pt, property)是如何工作的。

objectFactory属性

上篇文章中,提到在获取Container扩展点接口对应的ExtensionLoader的时候,会执行私有ExtensionLoader构造函数。
    private ExtensionLoader(Class<?> type) {
        this.type = type;
        objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
    }
因为此时type是Container.class,即objectFactory = ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension();
当type为ExtensionFactory.class时,即 objectFactory = null.
我们可以看出,所有非ExtensionFactory.class扩展点接口都会执行ExtensionFactory对应的ExtensionLoader实例的getAdaptiveExtension()方法返回一个ExtensionFactory实例,即objectFactory对象。否则,objectFactory对象为null。

核心方法 -> ExtensionLoader的getAdaptiveExtension方法源码

  • getAdaptiveExtension 获取带有Adaptive注解的扩展实现类

    • createAdaptiveExtension()创建实例

      • injectExtension() 自动注入IOC

        • getAdaptiveExtensionClass() ---执行cachedAdaptiveClass对象的构造函数

          • getExtensionClasses() ---解析所有的扩展点实现

            • loadExtensionClasses() ---加载扩展类

              • loadFile() --- 从固定的文件路径,解析加载对应的扩展点实现【上一篇已经说过,这个地方会加载几种情形的扩展实现类,包括拿到cachedAdaptiveClass对象】
          • 返回cachedAdaptiveClass --- 返回loadFile()方法中构造的cachedAdaptiveClass对象
        • 执行 cachedAdaptiveClass.newInstance() ---执行AdaptiveExtensionFactory的构造函数

ExtensionFactory的实现类AdaptiveExtensionFactory带有Adaptive标签,另外两个实现类SpiExtensionFactory、SpringExtensionFactory就是正常的实现类,也是我们见的最多的那种扩展点实现类。


### AdaptiveExtensionFactory源码
关键说明,
1. factories属性,所有的非@Adaptive类的ExtensionFactory实例的集合,以后所有与ExtensionFactory打交道的操作都交给AdaptiveExtensionFactory,
2. injectExtension方法中,调用的 Object object = objectFactory.getExtension(pt, property);分别调用SpiExtensionFactory、SpringExtensionFactory两个实际的实现类。
/**
 * AdaptiveExtensionFactory
 *
 * @author william.liangf
 */
@Adaptive
public class AdaptiveExtensionFactory implements ExtensionFactory {

    //所有的非@Adaptive类的ExtensionFactory实例的集合
    private final List<ExtensionFactory> factories;

    //因为ExtensionFactory对应的ExtensionLoader实例中缓存字段已经初始化好了,所以的ExtensionLoader的操作大都是从缓存中获取的数据
    public AdaptiveExtensionFactory() {
        //从缓存的static变量EXTENSION_LOADERS中拿到ExtensionFactory对应的ExtensionLoader实例
        ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
        List<ExtensionFactory> list = new ArrayList<ExtensionFactory>();
        //拿到loader中加载的普通的SPI扩展接口实现类的名称,spring与spi
        // adaptive=com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory
        // spi=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory
        for (String name : loader.getSupportedExtensions()) {
            //根据名称创建对应的ExtensionFactory实例
            list.add(loader.getExtension(name));
        }
        factories = Collections.unmodifiableList(list);
    }

    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;
    }

}

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)) {
                Object bean = context.getBean(name);
                if (type.isInstance(bean)) {
                    return (T) bean;
                }
            }
        }
        return null;
    }

}

是不是有一点熟悉的味道了啊,这也算是一个首尾呼应吧~

这一篇到时很快就写完了~ 下篇文章会讲解扩展点是如何实现AOP的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值