Jdk的SPI
SPI全称是Service Provider Interface,是JDK内置的一种服务提供发现机制。java.util.ServiceLoader提供了简单实现,以下是该实现的相关描述:
- 服务定义 如:com.example.CodecSet
- 服务实现 如:com.example.impl.StandardCodecs
- 服务配置文件
- 目录:META-INF/services
- 文件名:服务接口类的全名,如:META-INF/services/com.example.CodecSet
- 文件内容:服务实现类的全名,每行一个,如:com.example.impl.StandardCodecs
- 服务加载器 加载配置文件中的所有实现类
// JDK内部实现的服务发现类 提供懒加载机制
// 配置文件逐个懒加载,单个文件内的单行也逐个懒加载
private class LazyIterator implements Iterator<S>
{
Enumeration<URL> configs;// 所有配置文件路径
Iterator<String> pending;// 当前处理中的文件的内容,每行一个值
......
private boolean hasNextService() {
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;
}
private S nextService() {
if (!hasNextService()) throw new NoSuchElementException();
String cn = nextName;
nextName = null;
try {
// 获取实现类
c = Class.forName(cn, false, loader);
} catch (ClassNotFoundException x) {
fail(service, "Provider " + cn + " not found");
}
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
}
......
}
private LinkedHashMap<String,S> providers = new LinkedHashMap<>();
private LazyIterator lookupIterator;
// 对外提供的迭代器,遍历所有的实现类
public Iterator<S> iterator() {
return new Iterator<S>() {
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();
}
};
}
可见Jdk的插件化实现特别简单,约定 配置文件的格式,然后实现一个ServiceLoader通过配置文件加载相关实现类,并通过迭代器全部暴露出去。下面看下Dubbo的相关实现
Dubbo的SPI
Dubbo实现了一套更灵活的SPI插件化机制,首先配置文件中增加服务别名,另外新增注解@SPI, @Adaptive, @Activate, 决定激活哪个实现。@SPI指定默认激活的服务别名;@Adaptive是适配器注解,其值作为key从入参中取值即为服务别名;@Activate是激活类注解,其值作为key判定入参中是否存在,若存在就激活,常用于过滤器,指定哪些filter要执行。另外Dubbo还有Wrapper装箱类,在获取具体实现类时默认做封装操作
加载器
涉及到的缓存对象:
// 类型
private final Class<?> type;
// 扩展类-->别名
private final ConcurrentMap<Class<?>, String> cachedNames = new ConcurrentHashMap<Class<?>, String>();
// 别名-->扩展类
private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<Map<String, Class<?>>>();
// 别名-->类上的@Activate注解
private final Map<String, Object> cachedActivates = new ConcurrentHashMap<String, Object>();
// 缓存适配器类
private volatile Class<?> cachedAdaptiveClass = null;
// 默认别名
private String cachedDefaultName;
// 缓存包装类,自动装箱时,对原对象进行封装
private Set<Class<?>> cachedWrapperClasses;
加载所有扩展并缓存的服务:
// synchronized in getExtensionClasses
// 加载所有扩展并返回
private Map<String, Class<?>> loadExtensionClasses() {
// @SPI指定默认取值
final SPI defaultAnnotation = type.getAnnotation(SPI.class);
if (defaultAnnotation != null) {
String value = defaultAnnotation.value();
if ((value = value.trim()).length() > 0) {
String[] names = NAME_SEPARATOR.split(value);
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];
}
}
// 依次从三类目录中读取对应服务的配置文件
// repalce是为了兼容原有包名为com.alibaba的旧服务
Map<String, Class<?>> extensionClasses = new HashMap<String, Class<?>>();
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;
}
// 从配置目录中 找到对应的配置文件,并读取
private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir, String type) {
String fileName = dir + type;
try {
Enumeration<java.net.URL> urls;
ClassLoader classLoader = findClassLoader();
if (classLoader != null) {
urls = classLoader.getResources(fileName);
} else {
urls = ClassLoader.getSystemResources(fileName);
}
if (urls != null) {
// 依次读取
while (urls.hasMoreElements()) {
java.net.URL resourceURL = urls.nextElement();
loadResource(extensionClasses, classLoader, resourceURL);
}
}
} catch (Throwable t) {
logger.error("Exception when load extension class(interface: " +
type + ", description file: " + fileName + ").", t);
}
}
// 从具体文件中读取所有扩展
private void loadResource(Map<String, Class<?>> extensionClasses, ClassLoader classLoader, java.net.URL resourceURL) {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(resourceURL.openStream(), "utf-8"));
try {
String line;
while ((line = reader.readLine()) != null) {
// #后面的作为注释
final int ci = line.indexOf('#');
if (ci >= 0) line = line.substring(0, ci);
line = line.trim();
if (line.length() > 0) {
try {
String name = null;
int i = line.indexOf('=');
if (i > 0) {
name = line.substring(0, i).trim();
line = line.substring(i + 1).trim();
}
if (line.length() > 0) {
// 逐行读取,并加载相关实现类
loadClass(extensionClasses, resourceURL, Class.forName(line, true, classLoader), name);
}
} catch (Throwable t) {
}
}
}
} finally {
reader.close();
}
} catch (Throwable t) {
}
}
// extensionClasses-扩展类缓存
// resourceURL-配置文件地址
// clazz-服务实现类
// name-服务别名
private void loadClass(Map<String, Class<?>> extensionClasses, java.net.URL resourceURL, Class<?> clazz, String name) throws NoSuchMethodException {
if (!type.isAssignableFrom(clazz)) {
throw new IllegalStateException("Error when load extension class(interface: " + ...);
}
// 适配器类:不能多于1个
if (clazz.isAnnotationPresent(Adaptive.class)) {
if (cachedAdaptiveClass == null) {
cachedAdaptiveClass = clazz;
} else if (!cachedAdaptiveClass.equals(clazz)) {
throw new IllegalStateException("More than 1 adaptive class found: " + ...);
}
// 包装类直接放入缓存
} else if (isWrapperClass(clazz)) {
cachedWrapperClasses.add(clazz);
// 其余的都作为普通实现类
} else {
clazz.getConstructor();
if (name == null || name.length() == 0) {
// 别名默认从类名中取
name = findAnnotationName(clazz);
}
String[] names = NAME_SEPARATOR.split(name);
if (names != null && names.length > 0) {
Activate activate = clazz.getAnnotation(Activate.class);
if (activate != null) {
// 缓存类级别的激活注解
cachedActivates.put(names[0], activate);
} else {
// support com.alibaba.dubbo.common.extension.Activate
...
}
for (String n : names) {
// 缓存别名
if (!cachedNames.containsKey(clazz)) { cachedNames.put(clazz, n); }
// 缓存扩展
Class<?> c = extensionClasses.get(n);
if (c == null) {
extensionClasses.put(n, clazz);
} else if (c != clazz) {
// 别名重复抛异常
}
}
}
}
}
这里的加载器功能,将所有配置文件中的扩展类加载并缓存起来,分为适配器类、包装类、普通实现类。
扩展注入
// 扩展实例缓存
private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<Class<?>, Object>();
// 别名-->依赖注入、自动装箱后的实例
private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<String, Holder<Object>>();
// 适配器对象
private final Holder<Object> cachedAdaptiveInstance = new Holder<Object>();
// 指定别名查找对应的扩展类
@SuppressWarnings("unchecked")
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;
}
private T createExtension(String name) {
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);
}
// 依赖注入
injectExtension(instance);
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);
}
}
private T injectExtension(T instance) {
try {
if (objectFactory != null) {
for (Method method : instance.getClass().getMethods()) {
// 处理所有set方法
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;
}
这里在第一次获取实例时,会做一个依赖注入、自动装箱操作。依赖注入简单来说就是从对象工厂取对象出来,放入实例的set方法中;自动装箱就是使用装箱类的又参数构造器,构造包含实例的装箱类。
对象工厂
private final ExtensionFactory objectFactory =
(type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
// 对象工厂的适配器类
@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;
}
}
// SPI对象工厂
public class SpiExtensionFactory implements ExtensionFactory {
@Override
public <T> T getExtension(Class<T> type, String name) {
if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {
ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(type);
if (!loader.getSupportedExtensions().isEmpty()) {
return loader.getAdaptiveExtension();
}
}
return null;
}
}
// Spring对象工厂
public class SpringExtensionFactory implements ExtensionFactory {
......
}
// 配置文件
adaptive=org.apache.dubbo.common.extension.factory.AdaptiveExtensionFactory
spi=org.apache.dubbo.common.extension.factory.SpiExtensionFactory
// 这个在dubbo-config-spring包下配置
spring=org.apache.dubbo.config.spring.extension.SpringExtensionFactory
对象工厂本身也是基于插件机制实现的,自定义了适配器类、spi、spring扩展实现类。适配器类依次从扩展实现类中取相应对象,取出来就返回。
@Activate
用于指定所有实现类中,哪些被激活。以下为用法描述:
/**
* 依据给定的标准 激活相应的扩展, 例如: 用于有多个实现类的Filter接口上,确定哪些Filter需要激活。
* Activate.group属性指定分组标准,指定分组的调用才激活,SPI框架确定有效的分组值。
* Activate.value属性指定入参URL中的参数key,入参中存在该参数才激活。
* 通过调用ExtensionLoader#getActivateExtension(URL, String, String)}获得所有给定标准下激活的扩展
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Activate {
String[] group() default {};
String[] value() default {};
@Deprecated
String[] before() default {};
@Deprecated
String[] after() default {};
// 绝对的执行顺序信息,值越大越靠前
int order() default 0;
}
// 在消费端和服务提供端都激活
@Activate(group = {Constants.PROVIDER, Constants.CONSUMER})
public class MonitorFilter implements Filter {......}
// 在消费端和服务提供端,入参包含CACHE_KEY时激活
@Activate(group = {Constants.CONSUMER, Constants.PROVIDER}, value = Constants.CACHE_KEY)
public class CacheFilter implements Filter {......}
// 在消费端和服务提供端,入参包含VALIDATION_KEY时激活
// order=10000 指定顺序,值越大越靠前
@Activate(group = {Constants.CONSUMER, Constants.PROVIDER}, value = Constants.VALIDATION_KEY, order = 10000)
public class ValidationFilter implements Filter {......}
以下为源码剖析 ExtensionLoader.java:
public List<T> getActivateExtension(URL url, String key, String group) {
String value = url.getParameter(key);
return getActivateExtension(url, value == null || value.length() == 0 ? null : Constants.COMMA_SPLIT_PATTERN.split(value), group);
}
// values-自定义的扩展的别名
public List<T> getActivateExtension(URL url, String[] values, String group) {
List<T> exts = new ArrayList<T>();
List<String> names = values == null ? new ArrayList<String>(0) : Arrays.asList(values);
// 加载默认扩展类
if (!names.contains(Constants.REMOVE_VALUE_PREFIX + Constants.DEFAULT_KEY)) {
getExtensionClasses();// 加载所有配置文件中的扩展
for (Map.Entry<String, Object> entry : cachedActivates.entrySet()) {
String name = entry.getKey();
Object activate = entry.getValue();
String[] activateGroup, activateValue;
if (activate instanceof Activate) {
activateGroup = ((Activate) activate).group();
activateValue = ((Activate) activate).value();
} else {
continue;
}
// group匹配:gourp为null时默认激活,否则判断group是否在activateGroup列表中
if (isMatchGroup(group, activateGroup)) {
T ext = getExtension(name);
// 非指定扩展
if (!names.contains(name) && !names.contains(Constants.REMOVE_VALUE_PREFIX + name)
// value匹配
&& isActive(activateValue, url)) {
exts.add(ext);
}
}
}
// 按order排序,before after已废弃
Collections.sort(exts, ActivateComparator.COMPARATOR);
}
// 加载用户自定义的扩展类
List<T> usrs = new ArrayList<T>();
for (int i = 0; i < names.size(); i++) {
String name = names.get(i);
if (!name.startsWith(Constants.REMOVE_VALUE_PREFIX) && !names.contains(Constants.REMOVE_VALUE_PREFIX + name)) {
// 若指定了默认扩展,则将default前面的扩展都作为默认扩展,放在扩展列表的头部
if (Constants.DEFAULT_KEY.equals(name)) {
if (!usrs.isEmpty()) {
exts.addAll(0, usrs);
usrs.clear();
}
} else {
T ext = getExtension(name);
usrs.add(ext);
}
}
}
// 用户自定义的扩展类,放在后面
if (!usrs.isEmpty()) {
exts.addAll(usrs);
}
return exts;
}
// 判断是否需要激活:url中存在参数keys中的一个
private boolean isActive(String[] keys, URL url) {
if (keys.length == 0) {
return true;
}
for (String key : keys) {
for (Map.Entry<String, String> entry : url.getParameters().entrySet()) {
String k = entry.getKey();
String v = entry.getValue();
if ((k.equals(key) || k.endsWith("." + key))
&& ConfigUtils.isNotEmpty(v)) {
return true;
}
}
}
return false;
}
Dubbo内的相关使用类 ProtocolFilterWrapper.java:
private final Protocol protocol;
// 通过堆栈的方式实现过滤器链
private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) {
Invoker<T> last = invoker;
// 获取所有激活的过滤器
List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group);
if (!filters.isEmpty()) {
for (int i = filters.size() - 1; i >= 0; i--) {
final Filter filter = filters.get(i);
final Invoker<T> next = last;
last = new Invoker<T>() {
......
@Override
public Result invoke(Invocation invocation) throws RpcException {
return filter.invoke(next, invocation);
}
......
};
}
}
return last;
}
@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);
}
@Adaptive
适配器类,可以自定义实现,也可以依赖插件机制的自动生成。 下面看下扩展机制的适配器自动生成实现,这个方法太重了,其实可以拆一下。实现的功能是从入参中取扩展别名,然后调用该扩展的实现类,达到通过入参自动调用不同实现的功能。
private String createAdaptiveExtensionClassCode() {
StringBuilder codeBuilder = new StringBuilder();
Method[] methods = type.getMethods();
// 必须有待适配的method
boolean hasAdaptiveAnnotation = false;
for (Method m : methods) {
if (m.isAnnotationPresent(Adaptive.class)) {
hasAdaptiveAnnotation = true;
break;
}
}
if (!hasAdaptiveAnnotation)
throw new IllegalStateException("No adaptive method on extension " + type.getName() + ", refuse to create the adaptive class!");
codeBuilder.append("package ").append(type.getPackage().getName()).append(";");
codeBuilder.append("\nimport ").append(ExtensionLoader.class.getName()).append(";");
codeBuilder.append("\npublic class ").append(type.getSimpleName()).append("$Adaptive").append(" implements ").append(type.getCanonicalName()).append(" {");
codeBuilder.append("\nprivate static final org.apache.dubbo.common.logger.Logger logger = org.apache.dubbo.common.logger.LoggerFactory.getLogger(ExtensionLoader.class);");
codeBuilder.append("\nprivate java.util.concurrent.atomic.AtomicInteger count = new java.util.concurrent.atomic.AtomicInteger(0);\n");
// 逐个方法生成代理
for (Method method : methods) {
Class<?> rt = method.getReturnType();
Class<?>[] pts = method.getParameterTypes();
Class<?>[] ets = method.getExceptionTypes();
Adaptive adaptiveAnnotation = method.getAnnotation(Adaptive.class);
StringBuilder code = new StringBuilder(512);
// 以下为方法体
if (adaptiveAnnotation == null) {
// 方法没有注解时不处理
code.append("throw new UnsupportedOperationException(\"method ")
.append(method.toString()).append(" of interface ")
.append(type.getName()).append(" is not adaptive method!\");");
} else {
int urlTypeIndex = -1;
for (int i = 0; i < pts.length; ++i) {
if (pts[i].equals(URL.class)) {
urlTypeIndex = i;
break;
}
}
// 找到URL参数
if (urlTypeIndex != -1) {
// Null Point check
String s = String.format("\nif (arg%d == null) throw new IllegalArgumentException(\"url == null\");",
urlTypeIndex);
code.append(s);
s = String.format("\n%s url = arg%d;", URL.class.getName(), urlTypeIndex);
code.append(s);
}
// 若没有URL参数,从每个入参的get方法中读取
else {
String attribMethod = null;
// find URL getter method
LBL_PTS:
for (int i = 0; i < pts.length; ++i) {
Method[] ms = pts[i].getMethods();
for (Method m : ms) {
String name = m.getName();
if ((name.startsWith("get") || name.length() > 3)
&& Modifier.isPublic(m.getModifiers())
&& !Modifier.isStatic(m.getModifiers())
&& m.getParameterTypes().length == 0
&& m.getReturnType() == URL.class) {
urlTypeIndex = i;
attribMethod = name;
break LBL_PTS;
}
}
}
if (attribMethod == null) {
throw new IllegalStateException("fail to create adaptive class for interface " + type.getName()
+ ": not found url parameter or url attribute in parameters of method " + method.getName());
}
// Null point check
String s = String.format("\nif (arg%d == null) throw new IllegalArgumentException(\"%s argument == null\");",
urlTypeIndex, pts[urlTypeIndex].getName());
code.append(s);
s = String.format("\nif (arg%d.%s() == null) throw new IllegalArgumentException(\"%s argument %s() == null\");",
urlTypeIndex, attribMethod, pts[urlTypeIndex].getName(), attribMethod);
code.append(s);
s = String.format("%s url = arg%d.%s();", URL.class.getName(), urlTypeIndex, attribMethod);
code.append(s);
}
String[] value = adaptiveAnnotation.value();
// 注解的value 未设置时,从类名中取
if (value.length == 0) {
char[] charArray = type.getSimpleName().toCharArray();
StringBuilder sb = new StringBuilder(128);
for (int i = 0; i < charArray.length; i++) {
if (Character.isUpperCase(charArray[i])) {
if (i != 0) {
sb.append(".");
}
sb.append(Character.toLowerCase(charArray[i]));
} else {
sb.append(charArray[i]);
}
}
value = new String[]{sb.toString()};
}
boolean hasInvocation = false;
for (int i = 0; i < pts.length; ++i) {
if (pts[i].getName().equals("org.apache.dubbo.rpc.Invocation")) {
// Null Point check
String s = String.format("\nif (arg%d == null) throw new IllegalArgumentException(\"invocation == null\");", i);
code.append(s);
// 入参中包含Invocation时,从里面取出methodName,再按照methodName从URL里取参数值
s = String.format("\nString methodName = arg%d.getMethodName();", i);
code.append(s);
hasInvocation = true;
break;
}
}
// 取出入参中指定的别名
String defaultExtName = cachedDefaultName;
String getNameCode = null;
for (int i = value.length - 1; i >= 0; --i) {
if (i == value.length - 1) {
if (null != defaultExtName) {
if (!"protocol".equals(value[i]))
if (hasInvocation)
getNameCode = String.format("url.getMethodParameter(methodName, \"%s\", \"%s\")", value[i], defaultExtName);
else
getNameCode = String.format("url.getParameter(\"%s\", \"%s\")", value[i], defaultExtName);
else
getNameCode = String.format("( url.getProtocol() == null ? \"%s\" : url.getProtocol() )", defaultExtName);
} else {
if (!"protocol".equals(value[i]))
if (hasInvocation)
getNameCode = String.format("url.getMethodParameter(methodName, \"%s\", \"%s\")", value[i], defaultExtName);
else
getNameCode = String.format("url.getParameter(\"%s\")", value[i]);
else
getNameCode = "url.getProtocol()";
}
} else {
if (!"protocol".equals(value[i]))
if (hasInvocation)
getNameCode = String.format("url.getMethodParameter(methodName, \"%s\", \"%s\")", value[i], defaultExtName);
else
getNameCode = String.format("url.getParameter(\"%s\", %s)", value[i], getNameCode);
else
getNameCode = String.format("url.getProtocol() == null ? (%s) : url.getProtocol()", getNameCode);
}
}
code.append("\nString extName = ").append(getNameCode).append(";");
// 未指定别名时 抛异常
String s = String.format("\nif(extName == null) " +
"throw new IllegalStateException(\"Fail to get extension(%s) name from url(\" + url.toString() + \") use keys(%s)\");",
type.getName(), Arrays.toString(value));
code.append(s);
// 按照别名,取对应的扩展
code.append(String.format("\n%s extension = null;\n try {\nextension = (%<s)%s.getExtensionLoader(%s.class).getExtension(extName);\n}catch(Exception e){\n",
type.getName(), ExtensionLoader.class.getSimpleName(), type.getName()));
code.append(String.format("if (count.incrementAndGet() == 1) {\nlogger.warn(\"Failed to find extension named \" + extName + \" for type %s, will use default extension %s instead.\", e);\n}\n",
type.getName(), defaultExtName));
// 异常时,按默认别名取扩展
code.append(String.format("extension = (%s)%s.getExtensionLoader(%s.class).getExtension(\"%s\");\n}",
type.getName(), ExtensionLoader.class.getSimpleName(), type.getName(), defaultExtName));
// 调用对应的方法,并返回
if (!rt.equals(void.class)) {
code.append("\nreturn ");
}
s = String.format("extension.%s(", method.getName());
code.append(s);
for (int i = 0; i < pts.length; i++) {
if (i != 0)
code.append(", ");
code.append("arg").append(i);
}
code.append(");");
}
// 以下为方法声明
codeBuilder.append("\npublic ").append(rt.getCanonicalName()).append(" ").append(method.getName()).append("(");
for (int i = 0; i < pts.length; i++) {
if (i > 0) {
codeBuilder.append(", ");
}
codeBuilder.append(pts[i].getCanonicalName());
codeBuilder.append(" ");
codeBuilder.append("arg").append(i);
}
codeBuilder.append(")");
if (ets.length > 0) {
codeBuilder.append(" throws ");
for (int i = 0; i < ets.length; i++) {
if (i > 0) {
codeBuilder.append(", ");
}
codeBuilder.append(ets[i].getCanonicalName());
}
}
codeBuilder.append(" {");
codeBuilder.append(code.toString());
codeBuilder.append("\n}");
}
codeBuilder.append("\n}");
if (logger.isDebugEnabled()) {
logger.debug(codeBuilder.toString());
}
return codeBuilder.toString();
}
总结
JDK实现了最基本的SPI机制,通过约定从配置文件中读取所有扩展,实现了一套懒加载的迭代器读取扩展,而相关扩展的使用需要用户自己实现。Dubbo的扩展配置文件增加了别名,并通过@Adaptive、@Activate以及入参的配合,实现了灵活的扩展使用方法,用户只需通过入参就能决定激活哪些扩展,无需实现新的使用方法。