Dubbo Wrapper 依赖注入机制分析
- 基于 2.7.0 版本
- 上一章:『Dubbo SPI源码分析』Wrapper 机制分析
- 创建测试 demo
package com.luban.dubbo_spi.api;
@SPI
public interface Car {
public void getColor();
public void getColorForUrl(URL url);
}
package com.luban.dubbo_spi.impl;
public class RedCar implements Car {
public void getColor() {
System.out.println("red");
}
@Override
public void getColorForUrl(URL url) {
}
}
package com.luban.dubbo_spi.impl;
@Adaptive
public class AdaptiveCar implements Car {
@Override
public void getColor() {
}
@Override
public void getColorForUrl(URL url) {
System.out.println("123123");
}
}
- 然后在 resources 创建一个目录 META-INF.services 目录
- 并在 META-INF.services 目录中创建文件 com.luban.dubbo_spi.api.Car 一定要与接口同名
red = com.luban.dubbo_spi.impl.RedCar
com.luban.dubbo_spi.impl.AdaptiveCar
package com.luban.dubbo_spi.api;
@SPI
public interface Driver {
public void getColorForUrl(URL url);
}
package com.luban.dubbo_spi.impl
public class Trucker implements Driver {
private Car car;
public void setCar(Car car) {
this.car = car;
}
@Override
public void getColorForUrl(URL url) {
car.getColorForUrl(url);
}
}
- 并在 META-INF.services 目录中创建文件 com.luban.dubbo_spi.api.Driver 一定要与接口同名
tru = com.luban.dubbo_spi.impl.Trucker
public class CarDemo {
public static void main(String[] args) {
ExtensionLoader<Driver> extensionLoader =
ExtensionLoader.getExtensionLoader(Driver.class);
Driver driver = extensionLoader.getExtension("tru");
Map<String, String> map = new HashMap<>();
map.put("car", "black");
URL url = new URL("","",1, map);
driver.getColorForUrl(url);
}
}
- 首先通过 ExtensionLoader.getExtensionLoader() 获取 Driver.class 的加载器,加载器的流程可以参考 『Dubbo SPI源码分析』SPI 机制分析。获取到加载器以后,从加载器中,拿出扩展类
public class CarDemo {
public static void main(String[] args) {
ExtensionLoader<Driver> extensionLoader =
ExtensionLoader.getExtensionLoader(Driver.class);
Driver driver = extensionLoader.getExtension("tru");
...
}
}
- 由于还没创建实体,所以同时需要执行 createExtension() 方法
public class ExtensionLoader<T> {
private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<String, Holder<Object>>();
...
public T getExtension(String name) {
if (StringUtils.isEmpty(name)) {
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;
}
}
- 创建时,首先通过 getExtensionClasses() 扫描目录的配置,获取所有配置的类,然后从中取出标识为 “tru” 的类,其中相关流程在 『Dubbo SPI源码分析』SPI 机制分析 分析过,就不再叙述。获取 com.luban.dubbo_spi.impl.Trucker 类后,执行依赖注入
public class ExtensionLoader<T> {
private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<Class<?>, Object>();
...
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 (CollectionUtils.isNotEmpty(wrapperClasses)) {
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);
}
}
}
- com.luban.dubbo_spi.impl.Trucker 的 ExtensionLoader 包含 AdaptiveExtensionFactory 的对象工厂,所以这次会尝试对创建后的实体判断是否需要执行依赖注入,主要是判断是否有公有的 set() 方法,然后取出属性名称,既 set[Name]() 中这个 Name 就是要注入的属性名称,case 这里是 “car”,然后入参就是代表对应的类,最后调用 AdaptiveExtensionFactory.getExtension() 获取实体类之后注入方法中
- 重点
- 依赖注入的类,一定要标注 @Adaptive 与 @SPI
- 被注入的类,要标注 @SPI,同时如果要注入依赖的话,需要实现 set[Name](),其中 Name 是名称,而入参是实现类
public class ExtensionLoader<T> {
private final ExtensionFactory objectFactory;
...
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())) {
if (method.getAnnotation(DisableInject.class) != null) {
continue;
}
Class<?> pt = method.getParameterTypes()[0];
if (ReflectUtils.isPrimitives(pt)) {
continue;
}
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;
}
}
- AdaptiveExtensionFactory 在执行的 getExtension() 方法时,会遍历所有在配置文件中,实现了 ExtensionFactory.class 接口的类,从而获取其中的实体,这里只有 1 个,就是 SpiExtensionFactory
@Adaptive
public class AdaptiveExtensionFactory implements ExtensionFactory {
private final List<ExtensionFactory> factories;
...
@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;
}
}
- 执行 SpiExtensionFactory 的 getExtension() 方法时,会先判断入参的 type(即 com.luban.dubbo_spi.api.Car)是否为接口,同时标注了 @SPI 注解,如果有,则先获取 com.luban.dubbo_spi.api.Car 的 ExtensionLoader(过程参考 『Dubbo SPI源码分析』SPI 机制分析 ),通过 getSupportedExtensions() 扫描所有配置文件中实现了 com.luban.dubbo_spi.api.Car 接口的类,然后获取 Adaptive 扩展类
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;
}
}
- 执行 ExtensionLoader 获取 Adaptive 扩展类时,先判断缓存 cachedAdaptiveInstance 是否有一个创建过的实体,如果有就返回,没有则创建
public class ExtensionLoader<T> {
private final Holder<Object> cachedAdaptiveInstance = new Holder<Object>();
private volatile Throwable createAdaptiveInstanceError;
...
public T getAdaptiveExtension() {
Object instance = cachedAdaptiveInstance.get();
if (instance == null) {
if (createAdaptiveInstanceError == null) {
synchronized (cachedAdaptiveInstance) {
instance = cachedAdaptiveInstance.get();
if (instance == null) {
try {
instance = createAdaptiveExtension();
cachedAdaptiveInstance.set(instance);
} catch (Throwable t) {
createAdaptiveInstanceError = t;
throw new IllegalStateException("fail to create adaptive instance: " + t.toString(), t);
}
}
}
} else {
throw new IllegalStateException("fail to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError);
}
}
return (T) instance;
}
}
- 执行 createAdaptiveExtension() 方法时,先获取 Adaptive 扩展类
public class ExtensionLoader<T> {
..
private T createAdaptiveExtension() {
try {
return injectExtension((T) getAdaptiveExtensionClass().newInstance());
} catch (Exception e) {
throw new IllegalStateException("Can not create adaptive extension " + type + ", cause: " + e.getMessage(), e);
}
}
}
- 首先执行一次 getExtensionClasses() 扫描目录获取 com.luban.dubbo_spi.api.Car 的实现类(上面获取过一次,其实已经缓存了),返回缓存的 @Adaptive 扩展类
public class ExtensionLoader<T> {
...
private Class<?> getAdaptiveExtensionClass() {
getExtensionClasses();
if (cachedAdaptiveClass != null) {
return cachedAdaptiveClass;
}
return cachedAdaptiveClass = createAdaptiveExtensionClass();
}
}
- 获取到 com.luban.dubbo_spi.api.Car 的扩展类并创建实体,然后对该类也执行依赖注入,但是我们的 case 也没在对 com.luban.dubbo_spi.impl.AdaptiveCar 再进行注入,所以就直接返回
public class ExtensionLoader<T> {
...
@SuppressWarnings("unchecked")
private T createAdaptiveExtension() {
try {
return injectExtension((T) getAdaptiveExtensionClass().newInstance());
} catch (Exception e) {
throw new IllegalStateException("Can not create adaptive extension " + type + ", cause: " + e.getMessage(), e);
}
}
}
- 当完成对 com.luban.dubbo_spi.impl.Trucker 注入以后,就可以使用 com.luban.dubbo_spi.impl.AdaptiveCar 这个属性
public class CarDemo {
public static void main(String[] args) {
ExtensionLoader<Driver> extensionLoader =
ExtensionLoader.getExtensionLoader(Driver.class);
Driver driver = extensionLoader.getExtension("tru");
Map<String, String> map = new HashMap<>();
map.put("car", "black");
URL url = new URL("","",1, map);
driver.getColorForUrl(url);
}
}
- 总结