共计 6418 个字符,预计需要花费 17 分钟才能阅读完成。
1、Dubbo 的 SPI 例子
@SPI
public interface Robot {void sayHello();
}
public class OptimusPrime implements Robot{
@Override
public void sayHello() {System.out.println("Hello, I am Optimus Prime.");
}
}
public class Bumblebee implements Robot{
@Override
public void sayHello() {System.out.println("Hello, I am Bumblebee.");
}
}
public class DubboSPITest {
@Test
public void sayHelloDubbo() throws Exception {ExtensionLoader<Robot> extensionLoader = ExtensionLoader.getExtensionLoader(Robot.class);
Robot optimusPrime = extensionLoader.getExtension("optimusPrime");
optimusPrime.sayHello();
Robot bumblebee = extensionLoader.getExtension("bumblebee");
bumblebee.sayHello();}
}
输出:
Hello, I am Optimus Prime.
Hello, I am Bumblebee.
2、Dubbo 的 SPI 源码分析
ExtensionLoader<Robot> extensionLoader = ExtensionLoader.getExtensionLoader(Robot.class);
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
ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
if (loader == null) {// 若缓存未命中, 则创建一个新的实例, 先简单看下 new ExtensionLoader<T>(type)
EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
}
return loader;
}
private ExtensionLoader(Class<?> type) {
this.type = type;
// 这里的 type 是 Robot.class, 所以会执行后面的代码, 加载并创建 SpiExtensionFactory 和 SpringExtensionFactory,
// 后面再分析
objectFactory = (type == ExtensionFactory.class ? null :
ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}
Robot optimusPrime = extensionLoader.getExtension("optimusPrime");
public T getExtension(String name) {if ("true".equals(name)) {return getDefaultExtension();
}
// Holder 也是用于持有对象的, 用作缓存
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) {// 创建拓展实例, 下面分析 createExtension(name)
instance = createExtension(name);
holder.set(instance);
}
}
}
return (T) instance;
}
private T createExtension(String name) {
// 从配置文件中加载所有的拓展类, 可得到“配置项名称”到“配置类”的映射关系表
// 加载完后根据 name 获取, 得到形如 com.alibaba.dubbo.demo.provider.spi.OptimusPrime
// 待会重点分析 getExtensionClasses(), 删去了一些非关键代码
Class<?> clazz = getExtensionClasses().get(name);
try {
// 也是尝试先从缓存获取, 获取不到通过反射创建一个并放到缓存中
T instance = (T) EXTENSION_INSTANCES.get(clazz);
if (instance == null) {EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
instance = (T) EXTENSION_INSTANCES.get(clazz);
}
// 依赖注入和 cachedWrapperClasses, 后面分析
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;
}
}
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 注解, 这里的 type 是在调用 getExtensionLoader 方法时传入的
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) {// 抛异常}
// 获取 @SPI 注解中的值, 并缓存起来, 可以关注下, 后面会用到
if (names.length == 1) cachedDefaultName = names[0];
}
}
Map<String, Class<?>> extensionClasses = new HashMap<String, Class<?>>();
// 加载指定文件夹下的配置文件,META-INF/services/、META-INF/dubbo/、META-INF/dubbo/internal/
loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY);
// 我是放在这个目录下的
loadDirectory(extensionClasses, DUBBO_DIRECTORY);
loadDirectory(extensionClasses, SERVICES_DIRECTORY);
return extensionClasses;
}
private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir) {
// fileName 是 META-INF/dubbo/com.alibaba.dubbo.demo.provider.spi.Robot
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()) {
// 一个 resourceURL 就是一个文件
java.net.URL resourceURL = urls.nextElement();
loadResource(extensionClasses, classLoader, resourceURL);
}
}
}
}
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);
}
}
}
}
}
}
}
private void loadClass(Map<String, Class<?>> extensionClasses, java.net.URL resourceURL,
Class<?> clazz, String name) throws NoSuchMethodException {
// clazz 必须是 type 类型的, 否则抛异常
if (!type.isAssignableFrom(clazz)) { }
// 判断 clazz 是否为标注了 @Adaptive 注解, 后面分析
if (clazz.isAnnotationPresent(Adaptive.class)) {if (cachedAdaptiveClass == null) {cachedAdaptiveClass = clazz;} else if (!cachedAdaptiveClass.equals(clazz)) {// 抛异常, 不能有多个标注有 @Adaptive 注解的类}
}
// 判断是否是 Wrapper 类型, 后面分析
else if (isWrapperClass(clazz)) {
Set<Class<?>> wrappers = cachedWrapperClasses;
if (wrappers == null) {cachedWrapperClasses = new ConcurrentHashSet<Class<?>>();
wrappers = cachedWrapperClasses;
}
wrappers.add(clazz);
}
// 程序进入此分支, 表明 clazz 是一个普通的拓展类,Robot 就是一个普通的拓展类
else {
// 检测 clazz 是否有默认的构造方法, 如果没有, 则抛出异常
clazz.getConstructor();
if (name == null || name.length() == 0) {name = findAnnotationName(clazz);
if (name.length() == 0) {// 抛异常}
}
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) {if (!cachedNames.containsKey(clazz)) {cachedNames.put(clazz, n);
}
Class<?> c = extensionClasses.get(n);
if (c == null) {
// 存储名称到 class 的映射关系, 这样就解析好了一行
extensionClasses.put(n, clazz);
} else if (c != clazz) {// 抛异常}
}
}
}
}
正文完