在dubbo源码中,经常会用到ExtensionLoader, 里面用到java的SPI机制。
ProxyFactory proxyFactory = ExtensionLoader.
getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
Protocol protocol = ExtensionLoader.
getExtensionLoader(Protocol.class).getAdaptiveExtension();
总结
1. 先判断类是否有@SPI注解
2. 根据指定的目录+类扫描文件里的内容,处理@Advice的类
3. 如果没有则生成XX@Advice的代码,并编译.
类的定义
- 类上标记@SPI(“xxx”)
- 方法上标记@Adaptive({Constants.PROXY_KEY})
@SPI("javassist")
public interface ProxyFactory {
@Adaptive({Constants.PROXY_KEY})
<T> T getProxy(Invoker<T> invoker) throws RpcException;
@Adaptive({Constants.PROXY_KEY})
<T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException;
}
@SPI("dubbo")
public interface Protocol {
/**
* 获取缺省端口,当用户没有配置端口时使用。
*
* @return 缺省端口
*/
int getDefaultPort();
/**
* 暴露远程服务:<br>
* 1. 协议在接收请求时,应记录请求来源方地址信息:RpcContext.getContext()
* .setRemoteAddress();
* 2. export()必须是幂等的,也就是暴露同一个URL的Invoker两次,和暴露一次没有区别。
* 3. export()传入的Invoker由框架实现并传入,协议不需要关心。
*
* @param <T> 服务的类型
* @param invoker 服务的执行体
* @return exporter 暴露服务的引用,用于取消暴露
* @throws RpcException 当暴露服务出错时抛出,比如端口已占用
*/
@Adaptive
<T> Exporter<T> export(Invoker<T> invoker) throws RpcException;
/**
* 引用远程服务:<br>
* 1. 当用户调用refer()所返回的Invoker对象的invoke()方法时,
* 协议需相应执行同URL远端export()传入的Invoker对象的invoke()方法。
* 2. refer()返回的Invoker由协议实现,协议通常需要在此Invoker中发送远程请求。
* 3. 当url中有设置check=false时,连接失败不能抛出异常,并内部自动恢复。
*
* @param <T> 服务的类型
* @param type 服务的类型
* @param url 远程服务的URL地址
* @return invoker 服务的本地代理
* @throws RpcException 当连接服务提供方失败时抛出
*/
@Adaptive
<T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;
/**
* 释放协议:<br>
* 1. 取消该协议所有已经暴露和引用的服务。
* 2. 释放协议所占用的所有资源,比如连接和端口。
* 3. 协议在释放后,依然能暴露和引用新的服务。
*/
void destroy();
}
获取ExtensionLoader对象
//存在ConcurrentHashMap中
private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS =
new ConcurrentHashMap<Class<?>, ExtensionLoader<?>>();
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
//不是接口,直接报错
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;
}
//查看类是不是有SPI注解
private static <T> boolean withExtensionAnnotation(Class<T> type) {
return type.isAnnotationPresent(SPI.class);
}
获取具体的对象
cachedAdaptiveClass : 获取到@Adaptive的类
cachedWrapperClasses : 获取到文件中所有的类
- 获取对象,没有则创建对象
public T getAdaptiveExtension() {
Object instance = cachedAdaptiveInstance.get();
if (instance == null) {
//......
instance = createAdaptiveExtension();
cachedAdaptiveInstance.set(instance);
//......
}
return (T) instance;
}
- 创建对象(获取到类再实例化)
private T createAdaptiveExtension() {
return injectExtension( (T) getAdaptiveExtensionClass().newInstance() );
}
- 获取到类
private Class<?> getAdaptiveExtensionClass() {
getExtensionClasses();
if (cachedAdaptiveClass != null) {
return cachedAdaptiveClass;
}
return cachedAdaptiveClass = createAdaptiveExtensionClass();
}
1. 根据type扫描指定包下的type文件
扫描指定路径下的所有type文件的内容。
根据文件里的类名去加载类
有@Adaptive的类放入到cachedAdaptiveClass
否则组装到cachedWrapperClasses (key:类,value:是别称)
cachedClasses:将所有的key和class封装起来
- 加载类
private Map<String, Class<?>> getExtensionClasses() {
Map<String, Class<?>> classes = cachedClasses.get();
if (classes == null) {
synchronized (cachedClasses) {
classes = cachedClasses.get();
if (classes == null) {
classes = loadExtensionClasses();
cachedClasses.set(classes);
}
}
}
return classes;
}
private Map<String, Class<?>> loadExtensionClasses() {
//有SPI注解
final SPI defaultAnnotation = type.getAnnotation(SPI.class);
//获取他的默认值
if(defaultAnnotation != null) {
String value = defaultAnnotation.value();
if(value != null && (value = value.trim()).length() > 0) {
String[] names = NAME_SEPARATOR.split(value);
if(names.length == 1) cachedDefaultName = names[0];
}
}
Map<String, Class<?>> extensionClasses = new HashMap<String, Class<?>>();
//通过dir + type.getName()去加载
//文件META-INF/services/com.alibaba.dubbo.xx.XX
loadFile(extensionClasses, DUBBO_INTERNAL_DIRECTORY);//META-INF/dubbo/internal/
loadFile(extensionClasses, DUBBO_DIRECTORY);//META-INF/dubbo/
loadFile(extensionClasses, SERVICES_DIRECTORY);//META-INF/services/
return extensionClasses;
}
- 加载文件(目录+文件名去加载文件)
private void loadFile(Map<String, Class<?>> extensionClasses, String dir) {
//目录+文件名 META-INF/services/com.alibaba.dubbo.xx.XX
String fileName = dir + type.getName();
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()) {
//省略读取文件...
//格式如下:
//spring=com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory
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) {
Class<?> clazz = Class.forName(line, true, classLoader);
//如果这个类有Adaptive注解
if (clazz.isAnnotationPresent(Adaptive.class)) {
//记下来
if(cachedAdaptiveClass == null) {
cachedAdaptiveClass = clazz;
}
} else {
try {
//cachedWrapperClasses添加类
/**获取它的含有type的构造器
SpringExtensionFactory里必须有
SpringExtensionFactory(ExtensionFactory factory)构造器**/
clazz.getConstructor(type);
Set<Class<?>> wrappers = cachedWrapperClasses;
if (wrappers == null) {
cachedWrapperClasses = new ConcurrentHashSet<Class<?>>();
wrappers = cachedWrapperClasses;
}
wrappers.add(clazz);
} catch (NoSuchMethodException e) {
//获取默认构造器
clazz.getConstructor();
if (name == null || name.length() == 0) {
/**
1. 类有注解Extension,获取注解中的值
2. 类的名称clazz.getSimpleName()
**/
name = findAnnotationName(clazz);
if (name == null || name.length() == 0) {
if (clazz.getSimpleName().length() > type.
getSimpleName().length() && clazz.getSimpleName()
.endsWith(type.getSimpleName())) {
name = clazz.getSimpleName().substring(0, clazz.
getSimpleName().length() - type.getSimpleName().
length()).toLowerCase();
}
}
}
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);
}
for (String n : names) {
//往cachedNames放入类和key(spring)
if (! cachedNames.containsKey(clazz)) {
cachedNames.put(clazz, n);
}
Class<?> c = extensionClasses.get(n);
if (c == null) {
extensionClasses.put(n, clazz);
}
}
}
}
}
@Advice 的类
- AdaptiveExtensionFactory
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);
}
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
public class SpiExtensionFactory implements ExtensionFactory {
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().size() > 0) {
return loader.getAdaptiveExtension();
}
}
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;
}
}
2. 如果上述没有@Advice的类,那么就自己生成 ExtensionFactory 代码
- 创建code代码
- 编译
private Class<?> createAdaptiveExtensionClass() {
String code = createAdaptiveExtensionClassCode();
ClassLoader classLoader = findClassLoader();
com.alibaba.dubbo.common.compiler.Compiler compiler =
ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.
Compiler.class).getAdaptiveExtension();
return compiler.compile(code, classLoader);
}
- 创建AdaptiveExtension的代码
private String createAdaptiveExtensionClassCode() {
StringBuilder codeBuidler = new StringBuilder();
//遍历类的方法上是否有@Adaptive
Method[] methods = type.getMethods();
boolean hasAdaptiveAnnotation = false;
for(Method m : methods) {
if(m.isAnnotationPresent(Adaptive.class)) {
hasAdaptiveAnnotation = true;
break;
}
}
// 完全没有Adaptive方法,则不需要生成Adaptive类
if(! hasAdaptiveAnnotation)
throw new IllegalStateException("");
//...省略
return codeBuidler.toString();
}
生成的代码eg:
比如type是Protocol
package com.alibaba.dubbo.rpc;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
public class Protocol$Adpative implements com.alibaba.dubbo.rpc.Protocol {
public void destroy() {
throw new UnsupportedOperationException("..");
}
public int getDefaultPort() {
throw new UnsupportedOperationException("..");
}
public com.alibaba.dubbo.rpc.Exporter export(com.alibaba.dubbo.rpc.Invoker arg0)
throws com.alibaba.dubbo.rpc.Invoker {
if (arg0 == null)
throw new IllegalArgumentException("..");
if (arg0.getUrl() == null)
throw new IllegalArgumentException("..");
com.alibaba.dubbo.common.URL url = arg0.getUrl();
String extName = ( url.getProtocol() == null ?
"dubbo" : url.getProtocol() );
if(extName == null)
throw new IllegalStateException("..");
com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol)
ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class)
.getExtension(extName);
return extension.export(arg0);
}
public com.alibaba.dubbo.rpc.Invoker refer(
java.lang.Class arg0, com.alibaba.dubbo.common.URL arg1)
throws java.lang.Class {
if (arg1 == null)
throw new IllegalArgumentException("url == null");
com.alibaba.dubbo.common.URL url = arg1;
String extName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() );
if(extName == null)
throw new IllegalStateException("..");
com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol)
ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class)
.getExtension(extName);
return extension.refer(arg0, arg1);
}
}
可以参考https://blog.csdn.net/quhongwei_zhanqiu/article/details/41577235