SPI(Service Provider Interface)是一种服务提供发现机制,一个服务通常指的是已知的接口,服务提供方就是这个接口的实现类,然后按照SPI标准存放到资源路径META-INF/services目录下,文件的命名为该服务接口的全限定名。
这里会介绍两种SPI机制:JDK默认提供的SPI机制 ServiceLoader;Dubbo的SPI机制 ExtensionLoader。ServiceLoader功能比较单一,不能依赖注入、不能根据扩展实现类标识符获取特定的扩展实现类实例;
ServiceLoader
测试案例
有一个服务
package com.zto.sxy.helloworld;
public interface ISPI {
void say();
}
实现类SPITestA
package com.zto.sxy.helloworld;
public class SPITestA implements ISPI{
@Override
public void say() {
System.out.println("SPI with implement testA");
}
}
实现类SPITestB
package com.zto.sxy.helloworld;
public class SPITestB implements ISPI{
@Override
public void say() {
System.out.println("SPI with implement testB");
}
}
然后在resources目录下添加META-INF/services文件夹,同时新建一个名为com.zto.sxy.helloworld.ISPI的文件,内容如下:
com.zto.sxy.helloworld.SPITestA
com.zto.sxy.helloworld.SPITestB
以下是测试类
public class TestSPI {
@Test
public void testWithNoSPI(){
ISPI testA = new SPITestA();
testA.say();
ISPI testB = new SPITestB();
testB.say();
}
@Test
public void testWithSPI(){
ServiceLoader services = ServiceLoader.load(ISPI.class);
for (Iterator<ISPI> iterator = services.iterator(); iterator.hasNext(); ) {
ISPI spi = iterator.next();
spi.say();
}
}
}
执行测试函数,发现两个输出结果一样,说明SPI生效了,输出结果如下:
SPI with implement testA
SPI with implement testB
实现原理
先看load方法
public static <S> ServiceLoader<S> load(Class<S> service) {
// 获取当前线程上下文类加载器
ClassLoader cl = Thread.currentThread().getContextClassLoader();
return ServiceLoader.load(service, cl);
}
public static <S> ServiceLoader<S> load(Class<S> service,ClassLoader loader){
return new ServiceLoader<>(service, loader);
}
private ServiceLoader(Class<S> svc, ClassLoader cl) {
service = Objects.requireNonNull(svc, "Service interface cannot be null");
loader = (cl == null) ? ClassLoader.getSystemClassLoader() : cl;
acc = (System.getSecurityManager() != null) ? AccessController.getContext() : null;
// 清空缓存,确保会重新加载
reload();
}
在调用的的时候,先通过调用iterator方法返回一个Iterator对象,然后遍历该Iterator对象
public Iterator<S> iterator() {
return new Iterator<S>() {
// private LinkedHashMap<String,S> providers = new LinkedHashMap<>();
Iterator<Map.Entry<String,S>> knownProviders
= providers.entrySet().iterator();
public boolean hasNext() {
if (knownProviders.hasNext())
return true;
return lookupIterator.hasNext();
}
public S next() {
if (knownProviders.hasNext())
return knownProviders.next().getValue();
return lookupIterator.next();
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
调用hasNext方法的时候,会调用lookupIterator.hasNext()
private boolean hasNextService() {
if (nextName != null) {
return true;
}
if (configs == null) {
try {
String fullName = PREFIX + service.getName();
if (loader == null)
configs = ClassLoader.getSystemResources(fullName);
else
configs = loader.getResources(fullName);
} catch (IOException x) {
fail(service, "Error locating configuration files", x);
}
}
while ((pending == null) || !pending.hasNext()) {
if (!configs.hasMoreElements()) {
return false;
}
// 获取所有类的全类名
pending = parse(service, configs.nextElement());
}
nextName = pending.next();
return true;
}
当调用next方法的时候
private S nextService() {
if (!hasNextService())
throw new NoSuchElementException();
String cn = nextName;
nextName = null;
Class<?> c = null;
try {
c = Class.forName(cn, false, loader);
} catch (ClassNotFoundException x) {
fail(service,
"Provider " + cn + " not found");
}
if (!service.isAssignableFrom(c)) {
fail(service,
"Provider " + cn + " not a subtype");
}
try {
// 实例化
S p = service.cast(c.newInstance());
providers.put(cn, p);
return p;
} catch (Throwable x) {
fail(service,
"Provider " + cn + " could not be instantiated",
x);
}
throw new Error(); // This cannot happen
}
ServiceLoader不是一实例化以后立马就去读配置文件中的服务实现者并实例化,而是等其Iterator实现获取对应的服务提供者时才会加载对应的配置文件进行解析,在调用Iterator的hasNext方法时会去加载配置文件进行解析,在调用next方法时会将对应的服务提供者进行实例化并进行缓存。
ExtensionLoader
测试案例
@Test
public void test() {
ExtensionLoader loader = ExtensionLoader.getExtensionLoader(Protocol.class);
Protocol protocol = (Protocol) loader.getExtension("dubbo");
}
/**
* 1. ExtensionLoader loder = ExtensionLoader.getExtensionLoader(Protocol.class); 返回 loader1
* 1.1 创建一个ExtensionLoader实例(loader1),此时 loader1 的 type=Protocol.class,在为 loader1 的 objectFactory 属性赋值的时候,触发 ExtensionFactory 对应的ExtensionLoader实例化;
*
* 1.2 创建一个ExtensionLoader实例(loader2),此时 loader2 的 type=ExtensionFactory.class,objectFactory = null;
*
* 1.3 执行 loader2 的 getAdaptiveExtension() 方法, 生成一个 AdaptiveExtensionFactory 实例(extensionFactoryAdaptive),赋值给 loader1 的 objectFactory 属性;
* 1.3.1 先从缓存中找到,中不到就执行 loadExtensionClasses() 方法,该方法会从配置文件中加载 ExtensionFactory 所有实现类的class对象,同事可以将 adaptive 和 wrapper 类型的是实现类缓存起来
* 1.3.2 找到 ExtensionFactory 对应的 adaptive实现类是 AdaptiveExtensionFactory,然后通过反射创建 AdaptiveExtensionFactory 实例(extensionFactoryAdaptive);
* 1.3.2.1 在 AdaptiveExtensionFactory 构造函数中,通过 loader2.getSupportedExtensions() 方法找到 spi(1.2.1中缓存起来的), 然后调用 loader2.getExtension("spi");
* 1.3.2.2 在 loader2.getExtension("spi") 方法中通过反射生成一个 SpiExtensionFactory 实例(spiExtensionFactory);
* 1.3.2.3 将 1.2.2.2 中生成的 SpiExtensionFactory 实例(spiExtensionFactory) 保存到 extensionFactoryAdaptive的factories属性中;
*
* 1.4 将 1.3 中生成的 AdaptiveExtensionFactory 实例(extensionFactoryAdaptive) 赋值给loader2的 objectFactory 属性,即 loader.objectFactory = extensionFactoryAdaptive;
*
*
* 2. Protocol protocol = (Protocol) loder.getExtension("dubbo"); 这里的 loader 对应上面的 loader1
* 2.1 先从缓存中获取,如果缓存中没有,就获取dubbo对应实现类的class对象,然后通过通过反射创建实例并放入缓存;
*
* 2.2 执行 injectExtension 方法,这是依赖注入相关的方法,可以注入 spring里面的bean对象 和 SPI对象;
* 2.2.1 找到实例的 setter 方法;
* 2.2.2 执行 objectFactory.getExtension 方法,这里的 objectFactory 就是指 extensionFactoryAdaptive;
* 2.2.3 执行 extensionFactoryAdaptive.getExtension 方法,然后在 该方法内部调用 spiExtensionFactory.getExtension 方法;
* 2.2.4 在 spiExtensionFactory.getExtension 方法内部找到对应的adaptive实例;
*
* 2.3 执行 wrapper 操作,即给实例 一层一层的包装,类似于多层代理;
*
* 2.4 返回最终的实例;
*/
实现原理
在此之前,先看看ExtensionLoader中一些属性的含义
快速预览
private static final Logger logger = LoggerFactory.getLogger(ExtensionLoader.class);
private static final String SERVICES_DIRECTORY = "META-INF/services/";
private static final String DUBBO_DIRECTORY = "META-INF/dubbo/";
private static final String DUBBO_INTERNAL_DIRECTORY = DUBBO_DIRECTORY + "internal/";
private static final Pattern NAME_SEPARATOR = Pattern.compile("\\s*[,]+\\s*");
// 所有ExtensionLoader实例共享,缓存 对应扩展接口:ExtensionLoader实例
private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<>();
// 所有ExtensionLoader实例共享,缓存 对应实现类class对象:对应的实现类实例
private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<>();
// 扩展接口Class对象
private final Class<?> type;
private final ExtensionFactory objectFactory;
// 缓存 实现类Class对象:实现类标识
private final ConcurrentMap<Class<?>, String> cachedNames = new ConcurrentHashMap<>();
// 缓存当前扩展下所有实现类的 Class对象
private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<>();
// 缓存带有@Active注解的实现类,实现类标识:实现类Class对象,@Active注解表示该扩展实现类的激活条件和时机
private final Map<String, Object> cachedActivates = new ConcurrentHashMap<>();
// 缓存 实现类标识:Holder,因为种扩展都对应一个ExtensionLoader实例,所以通过实现类标识可以区分实现类
private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<>();
// 缓存 带有@Adaptive注解的实现类的实例,因为每种扩展只能有一个实现类带有@Adaptive注解
private final Holder<Object> cachedAdaptiveInstance = new Holder<>();
// 缓存 带有@Adaptive注解的实现类Class对象,因为每种扩展只能有一个实现类带有@Adaptive注解
private volatile Class<?> cachedAdaptiveClass = null;
private String cachedDefaultName;
private volatile Throwable createAdaptiveInstanceError;
// 缓存 包装类 实现类里参数是接口类型的(如 com.alibaba.dubbo.rpc.Protocol类型,并且只有1个参数)的构造函数,表示它是个接口包装类
private Set<Class<?>> cachedWrapperClasses;
private Map<String, IllegalStateException> exceptions = new ConcurrentHashMap<>();
getExtensionLoader
getExtensionLoader是一个静态方法,用于获取一个ExtensionLoader实例,每种扩展对应一个ExtensionLoader实例,缓存在一个静态ConcurrentMap中
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 interface!");
}
// 检查是否有@SPI注解
if (!withExtensionAnnotation(type)) {
throw new IllegalArgumentException("Extension type(" + type +
") is not extension, because WITHOUT @" + SPI.class.getSimpleName() + " Annotation!");
}
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;
}
private ExtensionLoader(Class<?> type) {
this.type = type;
// 在创建ExtensionLoader实例的过程中,涉及到和ExtensionFactory扩展相关的操作,这个在下面会有详细介绍
objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}
getExtension
每种扩展对应一个ExtensionLoader实例,每个ExtensionLoader实例中缓存了很多和当前扩展相关的信息,例如:该扩展的实现类、带有@Adaptive注解的扩展实现类、Wrapper实现类等等。getExtension主要是根据扩展实现类标识符获取对应的扩展实现类实例:
public T getExtension(String name) {
if (name == null || name.length() == 0)
throw new IllegalArgumentException("Extension name == null");
if ("true".equals(name)) {
return getDefaultExtension();
}
Holder<Object> holder = cachedInstances.get(name);
if (holder == null) {
cachedInstances.putIfAbsent(name, new Holder<Object>());
holder = cachedInstances.get(name);
}
Object instance = holder.get();
// 双重校验
if (instance == null) {
synchronized (holder) {
instance = holder.get();
if (instance == null) {
// 根据扩展名,获取具体扩展实例
instance = createExtension(name);
holder.set(instance);
}
}
}
return (T) instance;
}
createExtension
@SuppressWarnings("unchecked")
private T createExtension(String name) {
// 先从当前ExtensionLoader实例中的缓存中获取Class对象,如果没有就加载SPI相关文件
Class<?> clazz = getExtensionClasses().get(name);
if (clazz == null) {
throw findException(name);
}
try {
// 同步到静态缓存
T instance = (T) EXTENSION_INSTANCES.get(clazz);
if (instance == null) {
EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
instance = (T) EXTENSION_INSTANCES.get(clazz);
}
// 完成接口实现类依赖注入,依赖组件先从SPI机制构造查找,再从Spring容器查找(完成第2步)
injectExtension(instance);
// 如果这些实现类有wrapper类,当前实例instance,注入到包装类,包装类有多个,依次层层,循环构造注入;最后返回的是,最后一个包装类实例,这也是dubbo的aop实现机制
Set<Class<?>> wrapperClasses = cachedWrapperClasses;
if (wrapperClasses != null && !wrapperClasses.isEmpty()) {
for (Class<?> wrapperClass : wrapperClasses) {
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
}
}
return instance;
} catch (Throwable t) {
throw new IllegalStateException("Extension instance(name: " + name + ", class: " +
type + ") could not be instantiated: " + t.getMessage(), t);
}
}
getExtensionClasses
获取实现类的Class对象,在加载文件的过程中,会将相应的信息放入缓存中
private Map<String, Class<?>> getExtensionClasses() {
// 从缓存中获取
Map<String, Class<?>> classes = cachedClasses.get();
if (classes == null) {
synchronized (cachedClasses) {
classes = cachedClasses.get();
if (classes == null) {
// 加载SPI相关文件
classes = loadExtensionClasses();
cachedClasses.set(classes);
}
}
}
return classes;
}
// synchronized in getExtensionClasses
private Map<String, Class<?>> loadExtensionClasses() {
final SPI defaultAnnotation = type.getAnnotation(SPI.class);
// 判断是否有@SPI注解
if (defaultAnnotation != null) {
String value = defaultAnnotation.value();
if ((value = value.trim()).length() > 0) {
String[] names = NAME_SEPARATOR.split(value);
// 只能有一个默认值:SPI(value="xxx"),默认实现xxx
if (names.length > 1) {
throw new IllegalStateException("more than 1 default extension name on extension " + type.getName()
+ ": " + Arrays.toString(names));
}
if (names.length == 1) cachedDefaultName = names[0];
}
}
// 读取三个目录下的spi 配置文件;/META-INF/dubbo/internal, /META-INF/dubbo, /META-INF/services
Map<String, Class<?>> extensionClasses = new HashMap<>();
loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName());
loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName());
loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName());
loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
return extensionClasses;
}
依赖注入
在实例化扩展实现类的时候,该实现类可能会依赖一些其他的对象,主要有两种:一种是Spring容易中的Bean对象;另一种是其它的扩展实现类对象。
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())) {
// 获取所有public类型,并且只有一个参数的以set开头的方法
Class<?> pt = method.getParameterTypes()[0];
try {
// 构造驼峰命名法,得到该set方法的参数的类型,即:要注入的对应类型
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) {
// 执行set方法,完成注入
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;
}
ExtensionFactory
有关于objectFactory对象,这里涉及到的内容比较多,在文章的开头已经提到过,这里详细解释一下
private ExtensionLoader(Class<?> type) {
this.type = type;
objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}
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 interface!");
}
if (!withExtensionAnnotation(type)) {
throw new IllegalArgumentException("Extension type(" + type +
") is not extension, because WITHOUT @" + SPI.class.getSimpleName() + " Annotation!");
}
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;
}
Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).
当执行以上语句的时候:
- 先创建Protocol对应的ExtensionLoader实例对象
- 在执行1的过程中,涉及到ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()操作,所以会先创建ExtensionFactory对应的ExtensionLoader实例对象,然后返回一个ExtensionFactory对象,赋值给Protocol对应的ExtensionLoader实例对象。
ExtensionFactory其实也是一个扩展,并且它有一个带有@Adaptive注解的扩展实现类:AdaptiveExtensionFactory
@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);
}
而根据getAdaptiveExtension()方法的名字也可以猜测出,这里应该是创建了一个AdaptiveExtensionFactory对象
public T getAdaptiveExtension() {
// 加载完SPI文件之后,如果有,就会放入缓存中
Object instance = cachedAdaptiveInstance.get();
if (instance == null) {
if (createAdaptiveInstanceError == null) {
synchronized (cachedAdaptiveInstance) {
instance = cachedAdaptiveInstance.get();
if (instance == null) {
try {
instance = createAdaptiveExtension();
cachedAdaptiveInstance.set(instance);
} catch (Throwable t) {
createAdaptiveInstanceError = t;
throw new IllegalStateException("fail to create adaptive instance: " + t.toString(), t);
}
}
}
} else {
throw new IllegalStateException("fail to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError);
}
}
return (T) instance;
}
private T createAdaptiveExtension() {
try {
// 也需要处理依赖注入
return injectExtension((T) getAdaptiveExtensionClass().newInstance());
} catch (Exception e) {
throw new IllegalStateException("Can not create adaptive extension " + type + ", cause: " + e.getMessage(), e);
}
}
private Class<?> getAdaptiveExtensionClass() {
// 这个方法有可能性触发SPI文件加载,当缓存中没有值得时候,就会加载SPI文件
getExtensionClasses();
if (cachedAdaptiveClass != null) {
return cachedAdaptiveClass;
}
// 代表 @Adaptive注解添加在了方法上
return cachedAdaptiveClass = createAdaptiveExtensionClass();
}
以下是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<>();
// getSupportedExtensions()返回的是 非包装类扩展,非Adaptive扩展,防止无限循环
for (String name : loader.getSupportedExtensions()) {
list.add(loader.getExtension(name));
}
factories = Collections.unmodifiableList(list);
}
@Override
public <T> T getExtension(Class<T> type, String name) {
// 除AdaptiveExtensionFactory外,依次调用所有ExtensionFactory实现类的getExtension方法,如果找到了,就直接退出
for (ExtensionFactory factory : factories) {
T extension = factory.getExtension(type, name);
if (extension != null) {
return extension;
}
}
return null;
}
}
SpiExtensionFactory 用于注入扩展实现类(非包装类扩展,非Adaptive扩展),SpringExtensionFactory用于注入Spring容器中的Bean。
getAdaptiveExtension
上面已经提到了getAdaptiveExtension方法,这个方法用于获取自适应的扩展实现类,这方法真的非常非常重要,在dubbo到处用到了这个特性。有关于@Adaptive注解,这里再详细说明一下:
@Adaptive用法有两种方式,一种在就配置在扩展实现类上,用于扩展实现类上时只能有一个;还有一种直接配置在方法上,这两种方式第一种优先,没有第一种,dubbo自动完成第二种Adaptive类的生成
- 在扩展实现类上加上@Adaptive注解,是最为明确的创建对应类型Adaptive类,优先级最高;
- @SPI注解中的value是默认值,如果通过URL获取不到关于取哪个类作为Adaptive类的话,就使用这个默认值,当然如果URL中可以获取到,就用URL中的;
- 可以在方法上增加@Adaptive注解,注解中的value与链接中的参数的key一致,链接中的key对应的value就是SPI中的name,获取相应的实现类;
其实主要代码都在这里
private Class<?> getAdaptiveExtensionClass() {
// 这个方法有可能性触发SPI文件加载,当缓存中没有值得时候,就会加载SPI文件
getExtensionClasses();
if (cachedAdaptiveClass != null) {
return cachedAdaptiveClass;
}
// 动态生成
return cachedAdaptiveClass = createAdaptiveExtensionClass();
}
// 动态生成源码,然后编译返回Class对象
private Class<?> createAdaptiveExtensionClass() {
// 创建代码的字符串形式
String code = createAdaptiveExtensionClassCode();
ClassLoader classLoader = findClassLoader();
// 通过SPI获取java 编译器
org.apache.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
// 编译源码返回Class对象
return compiler.compile(code, classLoader);
}
以下以Protocol为例进行讲解,因为Protocol对应的扩展实现类上都没有加@Adaptive注解,所以这里主要涉及到Protocol$Adaptive类的动态生成
@SPI("dubbo")
public interface Protocol {
@Adaptive
<T> Exporter<T> export(Invoker<T> invoker) throws RpcException;
@Adaptive
<T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;
}
使用的场景可能是这样的
private static final Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
Exporter<?> exporter = protocol.export(wrapperInvoker);
其动态生成的Protocol$Adaptive源码如下
package org.apache.dubbo.rpc;
import org.apache.dubbo.common.extension.ExtensionLoader;
public class Protocol$Adaptive implements org.apache.dubbo.rpc.Protocol {
private static final org.apache.dubbo.common.logger.Logger logger = org.apache.dubbo.common.logger.LoggerFactory.getLogger(ExtensionLoader.class);
private java.util.concurrent.atomic.AtomicInteger count = new java.util.concurrent.atomic.AtomicInteger(0);
public void destroy() {
throw new UnsupportedOperationException("method public abstract void org.apache.dubbo.rpc.Protocol.destroy() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!");
}
public int getDefaultPort() {
throw new UnsupportedOperationException("method public abstract int org.apache.dubbo.rpc.Protocol.getDefaultPort() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!");
}
public org.apache.dubbo.rpc.Invoker refer(java.lang.Class arg0, org.apache.dubbo.common.URL arg1) throws org.apache.dubbo.rpc.RpcException {
if (arg1 == null) throw new IllegalArgumentException("url == null");
org.apache.dubbo.common.URL url = arg1;
String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
if (extName == null)
throw new IllegalStateException("Fail to get extension(org.apache.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");
org.apache.dubbo.rpc.Protocol extension = null;
try {
extension = (org.apache.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName);
} catch (Exception e) {
if (count.incrementAndGet() == 1) {
logger.warn("Failed to find extension named " + extName + " for type org.apache.dubbo.rpc.Protocol, will use default extension dubbo instead.", e);
}
extension = (org.apache.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension("dubbo");
}
return extension.refer(arg0, arg1);
}
public org.apache.dubbo.rpc.Exporter export(org.apache.dubbo.rpc.Invoker arg0) throws org.apache.dubbo.rpc.RpcException {
if (arg0 == null) throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument == null");
if (arg0.getUrl() == null)
throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument getUrl() == null");
org.apache.dubbo.common.URL url = arg0.getUrl();
String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
if (extName == null)
throw new IllegalStateException("Fail to get extension(org.apache.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");
org.apache.dubbo.rpc.Protocol extension = null;
try {
extension = (org.apache.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName);
} catch (Exception e) {
if (count.incrementAndGet() == 1) {
logger.warn("Failed to find extension named " + extName + " for type org.apache.dubbo.rpc.Protocol, will use default extension dubbo instead.", e);
}
extension = (org.apache.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension("dubbo");
}
return extension.export(arg0);
}
}
以export方法为例,从方法参数中Invoker获取信息, 如果没有,就取@SPI注解中的默认值:dubbo,如果都没有值,就抛出IllegalStateException异常
Wrapper处理
在处理完一个扩展实现类的依赖注入问题之后,接下来需要处理的便是该扩展实现类的Wrapper问题。在dubbo中,扩展实现类里参数是接口类型的(如 com.alibaba.dubbo.rpc.Protocol类型,并且只有1个参数)的构造函数,表示它是个Wrapper类。为什么需要它的构造函数需要有一个接口类型的参数?主要是用于接收上层对应的扩展实现类,然后Wrapper类实现类接口,所以可以在方法中插入一些自己的逻辑,类似于代理模式。
以ProtocolFilterWrapper为例,主要在于给非Wrapper扩展实现类加强功能
public class ProtocolFilterWrapper implements Protocol {
private final Protocol protocol;
public ProtocolFilterWrapper(Protocol protocol) {
if (protocol == null) {
throw new IllegalArgumentException("protocol == null");
}
this.protocol = protocol;
}
@Override
public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
return protocol.export(invoker);
}
return protocol.export(buildInvokerChain(invoker, Constants.SERVICE_FILTER_KEY, Constants.PROVIDER));
}
@Override
public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
return protocol.refer(type, url);
}
return buildInvokerChain(protocol.refer(type, url), Constants.REFERENCE_FILTER_KEY, Constants.CONSUMER);
}
}
而有关于通过Wrappe类加强的逻辑
Set<Class<?>> wrapperClasses = cachedWrapperClasses;
if (wrapperClasses != null && !wrapperClasses.isEmpty()) {
for (Class<?> wrapperClass : wrapperClasses) {
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
}
}
就是将所有的Wrapper类包装在原始的扩展实现类上,在调用的时候,就会先执行所有Wrapper中对应的逻辑,然后再执行真正扩展实现类的逻辑。
网友评论