背景
- 首先我们根据配置来进行 SPI 扩展的加载,但是我不想在启动的时候让扩展被加载,而是根据请求参数来动态选择对应的扩展。
- Dubbo 通过一个代理机制实现了自适应扩展,简单来说就是为你想拓展的接口生成一个代理类,可以通过JDK 或者 javassist编译你生成的代理类代码,然后通过反射创建实例。
- 这个实例里面的实现会根据本来方法的请求参数得知需要的扩展类,然后通过 ExtensionLoader.getExtensionLoader(type.class).getExtension() 来获取真正的实例来调用。
- @Adptive 注解就是自适应扩展相关的注解,可以修饰类和方法上;修饰类的时候不会生成代理类,类本身就是代理类,修饰方法上的时候会生成代理类。
修饰类
EXtensionFactory接口
- AdaptiveExtensionFactory 用@Adptive修饰
- SpiExtensionFactory
- SpringExtensionFactory
或者ExtensionLoader类的构造函数也会通过 getAdaptiveExtension() 获取指定的扩展类的 ExtensionFactory
private ExtensionLoader(Class<?> type) {
this.type = type;
objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}
AdaptiveExtensionFactory
- 构造函数缓存所有的实现类
- getExtension() 返回缓存的一个实现类
@Adaptive
public class AdaptiveExtensionFactory implements ExtensionFactory {
private final List<ExtensionFactory> factories;
// 缓存所有的ExtensionFactory的实现类
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);
}
// 获取实例的时候遍历factory,只要有一个找到就返回
@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;
}
}
getAdaptiveExtension()
- 先从缓存中获取,如果没有则通过双重检测,调用 createAdaptiveExtension() 来创建实例。
public T getAdaptiveExtension() {
// 从缓存中获取实例
Object instance = cachedAdaptiveInstance.get();
// 双重检测 创建实例 createAdaptiveExtension()
if (instance == null) {
if (createAdaptiveInstanceError == null) {
synchronized (cachedAdaptiveInstance) {
instance = cachedAdaptiveInstance.get();
if (instance == null) {
try {
instance = createAdaptiveExtension();
cachedAdaptiveInstance.set(instance);
}
···························
}
return (T) instance;
}
createAdaptiveExtension
- 通过调用 getAdaptiveExtensionClass() 创建一个实例
- 并调用 injectExtension() 进行依赖注入
private T createAdaptiveExtension() {
try {
return injectExtension((T) getAdaptiveExtensionClass().newInstance());
}
····················
}
getAdaptiveExtensionClass
- 调用 getExtensionClasses() 之前分析过,主要过程就是获取路径下的对应接口的所有实现类,并缓存;参考 getExtensionClasses
- 如果类上面有 @Adaptive 注解修饰直接返回,如果没有动态生成类
private Class<?> getAdaptiveExtensionClass() {
getExtensionClasses();
// 如果有Adaptive注解在类上,直接返回该类
if (cachedAdaptiveClass != null) {
return cachedAdaptiveClass;
}
// 如果没有说明需要动态生成类
return cachedAdaptiveClass = createAdaptiveExtensionClass();
}
修饰方法
- @Adaptive 注解在方法上则需要动态拼接代码,然后动态生成类
createAdaptiveExtensionClass
- 调用 createAdaptiveExtensionClassCode()
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);
}
private String createAdaptiveExtensionClassCode() {
StringBuilder codeBuilder = new StringBuilder();
Method[] methods = type.getMethods();
boolean hasAdaptiveAnnotation = false;
·····················
}