Dubbo微容器详解
ExtensionLoader
三种注解
- SPI
- Adaptive
- Activate
How to Work
先看Java自带SPI(Service Provider Interface)
ServiceLoader是一个简单的服务提供者加载工具
(A simple service-provider loading facility)since JDK 1.6
简单的例子
一个关于Car的Interface
public interface Car {
void run();
}
- 2个Car是具体实现
public class RacingCar implements Car {
@Override
public void run() {
System.out.println("RacingCar Running...");
}
}
public class SportCar implements Car {
@Override
public void run() {
System.out.println("SportCar Running...");
}
}
- 调用类
public class Main {
public static void main(String[] agrs){
ServiceLoader<Car> serviceLoader = ServiceLoader.load(Car.class);
serviceLoader.forEach(car -> {
car.run();
});
}
}
META-INF/services/com.youzan.soa.Car 内容
com.youzan.soa.RacingCar
com.youzan.soa.SportCar
工程目录结构
Dubbo SPI机制
如何实现
- 构造一个ExtensionLoader实例
ExtensionLoader<SimpleExt> extensionLoader = ExtensionLoader.getExtensionLoader(SimpleExt.class);
流程
结合源码分析
private Map<String, Class<?>> loadExtensionClasses() {
final SPI defaultAnnotation = type.getAnnotation(SPI.class);
if(defaultAnnotation != null) {
String value = defaultAnnotation.value();
if(value != null && (value = value.trim()).length() > 0) {
//...省略次要部分代码
}
}
Map<String, Class<?>> extensionClasses = new HashMap<String, Class<?>>();
loadFile(extensionClasses, DUBBO_INTERNAL_DIRECTORY);
loadFile(extensionClasses, DUBBO_DIRECTORY);
loadFile(extensionClasses, SERVICES_DIRECTORY);
return extensionClasses;
}
真正加载SpiExtensionFactory和AdaptiveExtensionFactory的是loadExtensionClasses方法,干活是loadFile方法。loadExtensionClasses会去查找三个路径下对应的工厂类扩展点
在构造AdaptiveExtensionFactory的ExtensionLoader实例并不需要加载依赖
也就是AdaptiveExtensionFactory的ExtensionLoader实例objectFactory=null,而SimpleExt的ExtensionLoader实例objectFactory是AdaptiveExtensionFactory。
private ExtensionLoader(Class<?> type) {
this.type = type;
objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}
private T injectExtension(T instance) {
try {
if (objectFactory != null) {
//... 省略部分代码代码
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return instance;
}
获取扩展点
- 调用
SimpleExt simpleExt = extensionLoader.getExtension("impl1");
流程
源码分析
createExtension方法
private T createExtension(String name) {
Class<?> clazz = getExtensionClasses().get(name);
//...省略
try {
T instance = (T) EXTENSION_INSTANCES.get(clazz);
if (instance == null) {
EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance());
instance = (T) EXTENSION_INSTANCES.get(clazz);
}
injectExtension(instance);
//...省略
return instance;
} catch (Throwable t) {
//...省略
}
}
createExtension是创建扩展点的入口,先通过getExtensionClasses加载三个路径下对应的扩展类,然后调用injectExtension注入依赖
详细分析injectExtension方法
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())) {
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) {
//...省略
}
}
}
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return instance;
}
因为SimpleExt的ExtensionLoader实例objectFactory是AdaptiveExtensionFactory,所以if分支的代码会执行。SimpleExt实例impl1有依赖的属性dao如下, injectExtension是通过set方法注入依赖。 如果此时依赖没有创建好,通过objectFactory.getExtension递归创建扩展点
public class SimpleExtImpl1 implements SimpleExt {
public Dao dao;
public void setDao(Dao dao){
this.dao = dao;
}
public String echo(URL url, String s) {
return "Ext6Impl1-echo-" + ext1.echo(url, s);
}
}
- objectFactory.getExtension, objectFactory的实现类是AdaptiveExtensionFactory, getExtension方法是一个入口,最终干活的是在factories中即是SpiExtensionFactory
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.getExtension的内部调用ExtensionLoader.getExtensionLoader递归加载依赖
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;
}
}
至此SimpleExt的扩展点及其依赖都已经加载完毕,是不是和spring的依赖注入有点相似,简易版本的Spring依赖管理
- 下一篇讲介绍Dubbo微容器的启动