二、dubbo spi 源码分析

二、dubbo spi 源码分析

1、ExtensionLoader

ExtensionLoader 是dubbo spi 主要实现类,从字面意思可以看出是扩展加载器,是将配置文件与java的对应关系进行组装处理,从而得到我们需要的实际扩展处理类

ExtensionLoader 类中有两个静态属性 EXTENSION_LOADERS (缓存所有的ExtensionLoader) 和 EXTENSION_INSTANCES (缓存扩展实现)

 private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<>(64);

    private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<>(64);
1.1 getExtensionLoader 方法

在dubbo源码中获取扩展加载器的主要逻辑是在getExtensionLoader静态方法中

  public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
        if (type == null) {
            throw new IllegalArgumentException("Extension type == null");
        }
        if (!type.isInterface()) {
            throw new IllegalArgumentException("Extension type (" + type + ") is not an interface!");
        }
        //判断接口有没有声明@SPI注解
        if (!withExtensionAnnotation(type)) {
            throw new IllegalArgumentException("Extension type (" + type +
                    ") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!");
        }
        //先去缓存中查找有没有对应的扩展类加载器
        ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
        if (loader == null) {
            //创建一个扩展类加载器放到缓存从
            EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
            loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
        }
        return loader;
    }
1.2 ExtensionLoader 构造方法 new ExtensionLoader(type)
 private ExtensionLoader(Class<?> type) {
        this.type = type;
   objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}

可以看到如果参数type 不是 ExtensionFactory 将会获取ExtensionFactory 的类加载器,接着获取

ExtensionFactory 的自适应扩展类。

 ExtensionFactory  到底是什么呢?
@SPI
public interface ExtensionFactory {

    /**
     * Get extension.
     *
     * @param type object type.
     * @param name object name.
     * @return object instance.
     */
    <T> T getExtension(Class<T> type, String name);

}

org.apache.dubbo.common.extension.ExtensionFactory 文件中声明了以下SPI 实现:

adaptive=org.apache.dubbo.common.extension.factory.AdaptiveExtensionFactory
spi=org.apache.dubbo.common.extension.factory.SpiExtensionFactory

ExtensionFactory 也是一个被标记的扩展接口,再dubbo 中配置了两个扩展实现。而在dubbo-config-spring 的配置中我们可以找到另一个实现类:

spring=org.apache.dubbo.config.spring.extension.SpringExtensionFactory

获取到了ExtensionFactory 的扩展类加载器后,getAdaptiveExtension() 会做哪些事呢?

1.3 getAdaptiveExtension 方法
 public T getAdaptiveExtension() {
        //缓存中获取自适应扩展实例
        Object instance = cachedAdaptiveInstance.get();
        if (instance == null) {
            if (createAdaptiveInstanceError != null) {
                throw new IllegalStateException("Failed to create adaptive instance: " +
                        createAdaptiveInstanceError.toString(),
                        createAdaptiveInstanceError);
            }

            synchronized (cachedAdaptiveInstance) {
                //缓存中获取自适应扩展实例
                instance = cachedAdaptiveInstance.get();
                if (instance == null) {
                    try {
                        //创建自适应扩展实例
                        instance = createAdaptiveExtension();
                        //放入缓存中
                        cachedAdaptiveInstance.set(instance);
                    } catch (Throwable t) {
                        createAdaptiveInstanceError = t;
                        throw new IllegalStateException("Failed to create adaptive instance: " + t.toString(), t);
                    }
                }
            }
        }

        return (T) instance;
    }
    private T createAdaptiveExtension() {
        try {
            return injectExtension((T) getAdaptiveExtensionClass().newInstance());
        } catch (Exception e) {
            throw new IllegalStateException("Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e);
        }
    }
    private Class<?> getAdaptiveExtensionClass() {
        //根据对应的SPI文件加载扩展类并缓存,细节此处不展开
        getExtensionClasses();
        // 如果存在被@Adaptive修饰的类则直接返回此类
        if (cachedAdaptiveClass != null) {
            return cachedAdaptiveClass;
        }
        // 动态生成Xxxx$Adaptive类
        return cachedAdaptiveClass = createAdaptiveExtensionClass();
    }
//代理类
package com.jufeng.learn.other.api.dubbo.spi.demo03;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
public class SimpleEcho$Adaptive implements com.jufeng.learn.other.api.dubbo.spi.demo03.SimpleEcho {
  public void printA(java.lang.String arg0) {
    throw new UnsupportedOperationException("method public abstract void com.jufeng.learn.other.api.dubbo.spi.demo03.SimpleEcho.printA(java.lang.String) of interface com.jufeng.learn.other.api.dubbo.spi.demo03.SimpleEcho is not adaptive method!");
  }
  public void printB(com.alibaba.dubbo.common.URL arg0, java.lang.String arg1) {
    if (arg0 == null) throw new IllegalArgumentException("url == null");
    com.alibaba.dubbo.common.URL url = arg0;
    String extName = url.getParameter("simple.echo");
    if(extName == null) throw new IllegalStateException("Fail to get extension(com.jufeng.learn.other.api.dubbo.spi.demo03.SimpleEcho) name from url(" + url.toString() + ") use keys([simple.echo])");
    com.jufeng.learn.other.api.dubbo.spi.demo03.SimpleEcho extension = (com.jufeng.learn.other.api.dubbo.spi.demo03.SimpleEcho)ExtensionLoader.getExtensionLoader(com.jufeng.learn.other.api.dubbo.spi.demo03.SimpleEcho.class).getExtension(extName);extension.printB(arg0, arg1);
  }
}

至此,自适应扩展类就被加载完成,有兴趣可以看getExtensionClasses 方法是怎么实现读取 SPI配置文件以及 @Adaptive 和 URL 参数的解析校验。

下面一节,我们分析ExtensionFactory 的作用,以及在Dubbo是如何将SpringIOC 容器中的实例整合到Dubbo框架中。

2. ExtensionFactory

ExtensionFactory是dubbo框架中被标记的一个扩展接口,默认实现为AdaptiveExtensionFactory。

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

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

}
在无参的构造方法中可以看到,它会获取ExtensionFactory 的扩展类加载器,并将所有的实现类全部放入factories 属性中。而dubbo 以及 dubbo-config-spring 中配置的

spi=org.apache.dubbo.common.extension.factory.SpiExtensionFactory

spring=org.apache.dubbo.config.spring.extension.SpringExtensionFactory 都会被放入 factories 中。

SpringExtensionFactory 是我们重点关注的对象,下面看看它的实现:

public class SpringExtensionFactory implements ExtensionFactory {
    private static final Logger logger = LoggerFactory.getLogger(SpringExtensionFactory.class);
    private static final Set<ApplicationContext> CONTEXTS = new ConcurrentHashSet<ApplicationContext>();
    public static void addApplicationContext(ApplicationContext context) {
        CONTEXTS.add(context);
        if (context instanceof ConfigurableApplicationContext) {
            ((ConfigurableApplicationContext) context).registerShutdownHook();
        }
    }
    public static void removeApplicationContext(ApplicationContext context) {
        CONTEXTS.remove(context);
    }
    public static Set<ApplicationContext> getContexts() {
        return CONTEXTS;
    }
    // currently for test purpose
    public static void clearContexts() {
        CONTEXTS.clear();
    }
    @Override
    @SuppressWarnings("unchecked")
    public <T> T getExtension(Class<T> type, String name) {

        //SPI should be get from SpiExtensionFactory
        if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {
            return null;
        }
        for (ApplicationContext context : CONTEXTS) {
            T bean = getOptionalBean(context, name, type);
            if (bean != null) {
                return bean;
            }
        }
        return null;
    }

}


可以看到 SpringExtensionFactory 中维护了Spring上下文对象ApplicationContext,所以只要Spring的上下文对象被放入 SpringExtensionFactory CONTEXTS 属性中,Dubbo 就可以获取到SpringIOC 中的实例。

以ServiceBean 为例,在Dubbo中是对服务提供接口的一次封装,用于注入到Spring中,那么Dubbo 在暴露接口的时候是需要拿到IOC 中的一些实例,所以Dubbo是怎么做的呢?下面来看ServiceBean 的实现

public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean, DisposableBean,
        ApplicationContextAware, BeanNameAware, ApplicationEventPublisherAware {
         @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
        SpringExtensionFactory.addApplicationContext(applicationContext);
    }
......        
}

可以看到 ServiceBean 实现了 ApplicationContextAware ,而实现了ApplicationContextAware 接口将会在bean 的初始化之前执行,在执行setApplicationContext 方法时,会执行 SpringExtensionFactory.addApplicationContext(applicationContext) 这行代码,所以Spring的上下文对象就会被写入到 SpringExtensionFactory类的静态成员属性中,当dubbo需要取到 Spring IOC 中的对象时就可以根据 AdaptiveExtensionFactory.getExtension()方法进行获取(此处只是举例,在Spring 中 dubbo 的启动方式,服务暴露等详细内容将在其他章节中解析。)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值