实际工作中,我们希望实例能懒加载,或者运行期自动选择
注解 @Adaptive 能解决这个选择问题
- 注解在实例类上时,直接选此类为适配类(一个接口只允许一个类标记)
- 注解在接口方法上时,只为此方法生成代理逻辑(方法必须有参数为url或者参数有返回url的方法)
/**
* 各个实现类上面没有@Adaptive
* SPI上有注解@SPI("b")
* URL中有具体的值info.service=a,
* 则以URL为准,选择A实现
*/
@Test
public void test1(){
ExtensionLoader<InfoService> loader = ExtensionLoader.getExtensionLoader(InfoService.class);
InfoService adaptiveExtension = loader.getAdaptiveExtension();
//接口 InfoService
URL url = URL.valueOf("test://localhost/test?info.service=a");
System.out.println(adaptiveExtension.passInfo("james", url));
}
/**
* 各个实现类上面没有@Adaptive
* 接口方法中加上注解@Adaptive({"InfoService"}),
* URL中有具体的值InfoService=c,
* 则以URL中的InfoService参数为准,选择C实现
*/
@Test
public void test2(){
ExtensionLoader<InfoService> loader = ExtensionLoader.getExtensionLoader(InfoService.class);
InfoService adaptiveExtension = loader.getAdaptiveExtension();
URL url = URL.valueOf("test://localhost/test?info.service=a&InfoService=c");
System.out.println(adaptiveExtension.passInfo("james", url));
}
跟 getAdaptiveExtension:
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:
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);
}
}
跟 getAdaptiveExtensionClass:
private Class<?> getAdaptiveExtensionClass() {
getExtensionClasses();
if (cachedAdaptiveClass != null) {
return cachedAdaptiveClass;
}
return cachedAdaptiveClass = createAdaptiveExtensionClass();
}
跟 createAdaptiveExtensionClass:
private Class<?> createAdaptiveExtensionClass() {
//构建Class内容的字符串
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);
}