SPI机制
@Author:zxw
@school:吉首大学
参考资料:http://dubbo.apache.org/zh-cn/docs/source_code_guide/dubbo-spi.html
1. 前言
2. JAVA SPI
ServiceLoader<Robot> loader = ServiceLoader.load(Robot.class);
System.out.println("JAVA SPI");
loader.forEach(Robot::sayHello);
创建一个Iteraotor.iterator方法(),并创建一个接口
public S next() {
if (knownProviders.hasNext())
return knownProviders.next().getValue();
return lookupIterator.next();
}
首先通过next()方法获取下一元素
public S next() {
if (acc == null) {
// 进入这
return nextService();
} else {
PrivilegedAction<S> action = new PrivilegedAction<S>() {
public S run() { return nextService(); }
};
return AccessController.doPrivileged(action, acc);
}
}
private S nextService() {
// 判断是否有service
if (!hasNextService())
throw new NoSuchElementException();
String cn = nextName;
nextName = null;
Class<?> c = null;
try {
// 通过forName以及类的全限定名称加载
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
}
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;
}
3. Dubbo SPI
@Test
public void dubboHello() {
ExtensionLoader<Robot> extensionLoader = ExtensionLoader.getExtensionLoader(Robot.class);
Robot optimusPrime = extensionLoader.getExtension("optimusPrime");
optimusPrime.sayHello();
System.out.println("------");
Robot bumblebee = extensionLoader.getExtension("bumblebee");
bumblebee.sayHello();
}
现在看看extensionLoader.getExtension
方法中做了些什么。
public T getExtension(String name) {
// 判断名称是否为空
if (StringUtils.isEmpty(name)) {
// 抛出异常
throw new IllegalArgumentException("Extension name == null");
}
// 如果为ture,则获取默认扩展实现类
if ("true".equals(name)) {
return getDefaultExtension();
}
// 如果不存在,则添加进缓存实例map中
// 持有目标对象
final Holder<Object> holder = getOrCreateHolder(name);
Object instance = holder.get();
// 判断holder的值是否为空,如果为空则进行设置
// 双重检查
if (instance == null) {
synchronized (holder) {
instance = holder.get();
if (instance == null) {
// 创建拓展实例
instance = createExtension(name);
// 设置实例到holder中
holder.set(instance);
}
}
}
return (T) instance;
}
3.1 getDefaultExtension()
private Holder<Object> getOrCreateHolder(String name) {
Holder<Object> holder = cachedInstances.get(name);
if (holder == null) {
/**
* if (!map.containsKey(key))
* return map.put(key, value);
* else
* return map.get(key);
*/
// 创建一个Holder类(用于保存值)
cachedInstances.putIfAbsent(name, new Holder<>());
holder = cachedInstances.get(name);
}
return holder;
}
3.2 getOrCreateHolder()
private Holder<Object> getOrCreateHolder(String name) {
Holder<Object> holder = cachedInstances.get(name);
if (holder == null) {
/**
* if (!map.containsKey(key))
* return map.put(key, value);
* else
* return map.get(key);
*/
// 创建一个Holder类(用于保存持有对象)
cachedInstances.putIfAbsent(name, new Holder<>());
holder = cachedInstances.get(name);
}
return holder;
}
3.3 createExtension()
private T createExtension(String name) {
Class<?> clazz = getExtensionClasses().get(name);
if (clazz == null) {
throw findException(name);
}
try {
// 从map中获取该接口对应的实例
T instance = (T) EXTENSION_INSTANCES.get(clazz);
if (instance == null) {
// 设置实例
EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
instance = (T) EXTENSION_INSTANCES.get(clazz);
}
// 注入set方法
injectExtension(instance);
Set<Class<?>> wrapperClasses = cachedWrapperClasses;
if (CollectionUtils.isNotEmpty(wrapperClasses)) {
for (Class<?> wrapperClass : wrapperClasses) {
// 将当前 instance 作为参数传给 Wrapper 的构造方法,并通过反射创建 Wrapper 实例。
// 然后向 Wrapper 实例中注入依赖,最后将 Wrapper 实例再次赋值给 instance 变量
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
}
}
// LifeCycle组件初始化回调方法
initExtension(instance);
return instance;
} catch (Throwable t) {
throw new IllegalStateException("Extension instance (name: " + name + ", class: " +
type + ") couldn't be instantiated: " + t.getMessage(), t);
}
}
/**
* 默认加载以下两个Extension类
* spi -> org.apache.dubbo.common.extension.factory.SpiExtensionFactory
* spring -> org.apache.dubbo.config.spring.extension.SpringExtensionFactory
*/
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;
}
/**
* 去META-INF/dubbo 中加载Extension类
* 优先加载 /dubbo/internal 中的类
*/
private Map<String, Class<?>> loadExtensionClasses() {
// 获取注解中我们定义的名字
cacheDefaultExtensionName();
Map<String, Class<?>> extensionClasses = new HashMap<>();
// 依次从 dubbo/internal、dubbo/、services 三个路径下加载类
for (LoadingStrategy strategy : strategies) {
loadDirectory(extensionClasses, strategy.directory(), type.getName(), strategy.preferExtensionClassLoader(), strategy.excludedPackages());
loadDirectory(extensionClasses, strategy.directory(), type.getName().replace("org.apache", "com.alibaba"), strategy.preferExtensionClassLoader(), strategy.excludedPackages());
}
return extensionClasses;
}
private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir, String type,
boolean extensionLoaderClassLoaderFirst, String... excludedPackages) {
String fileName = dir + type;
try {
Enumeration<java.net.URL> urls = null;
ClassLoader classLoader = findClassLoader();
// try to load from ExtensionLoader's ClassLoader first
if (extensionLoaderClassLoaderFirst) {
ClassLoader extensionLoaderClassLoader = ExtensionLoader.class.getClassLoader();
if (ClassLoader.getSystemClassLoader() != extensionLoaderClassLoader) {
urls = extensionLoaderClassLoader.getResources(fileName);
}
}
// 判断路径下资源是否存在
if(urls == null || !urls.hasMoreElements()) {
if (classLoader != null) {
urls = classLoader.getResources(fileName);
} else {
urls = ClassLoader.getSystemResources(fileName);
}
}
if (urls != null) {
while (urls.hasMoreElements()) {
// 获取资源地址
java.net.URL resourceURL = urls.nextElement();
// 以 name -> class 存入map中
loadResource(extensionClasses, classLoader, resourceURL, excludedPackages);
}
}
} catch (Throwable t) {
logger.error("Exception occurred when loading extension class (interface: " +
type + ", description file: " + fileName + ").", t);
}
}
来源:oschina
链接:https://my.oschina.net/u/4182062/blog/4292218