Dubbo-Adaptive实现解析
程序员文章站
2022-06-01 20:00:35
...
Dubbo-Adaptive实现解析介
daptive的主要功能是对所有的扩展点进行封装为一个类,通过URL传入参数的时动态选择需要使用的
扩展点。其底层的实现原理就是动态代理
ExtensionLoader-getAdaptiveExtension
public T getAdaptiveExtension() {
//从缓存中获取 进行Holder和加锁的方式来保证只会被创建一次
Object instance = cachedAdaptiveInstance.get();
if (instance == null) {
//为空判断有没有错误 如果直接已经有创建并且错误的情况,则直接返回错误信息,防止重复没必要的创建
if (createAdaptiveInstanceError != null) {
throw new IllegalStateException("Failed to create adaptive instance: " +
createAdaptiveInstanceError.toString(),
createAdaptiveInstanceError);
}
//加锁
synchronized (cachedAdaptiveInstance) {
//再次从缓存中获取
instance = cachedAdaptiveInstance.get();
if (instance == null) {
try {
//创建AdaptiveExtension 这里真实的进行创建操作
instance = createAdaptiveExtension();
//放入缓存
cachedAdaptiveInstance.set(instance);
} catch (Throwable t) {
createAdaptiveInstanceError = t;
throw new IllegalStateException("Failed to create adaptive instance: " + t.toString(), t);
}
}
}
}
return (T) instance;
}
createAdaptiveExtension
/**
* 创建xxxAdaptive注解类的扩展
* @return
*/
@SuppressWarnings("unchecked")
private T createAdaptiveExtension() {
try {
//自动依赖注入injectExtension
// 这里使用`getAdaptiveExtensionClass`方法进行构建类并且执行实例化
// 然后和普通的其他class相同,依旧使用injectExtension进行扩展
return injectExtension((T) getAdaptiveExtensionClass().newInstance());
} catch (Exception e) {
throw new IllegalStateException("Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e);
}
}
injectExtension
private T injectExtension(T instance) {
//检测objectFactory字段
if (objectFactory == null) {
return instance;
}
try {
//遍历其中的所有方法
for (Method method : instance.getClass().getMethods()) {
//方法遍历判断是否为setter方法 如果不是,忽略该方法继续下一个方法
if (!isSetter(method)) {
// 是否是set方法
// 1. 以"set"开头
// 2. 参数长度为1
// 3. 是公开的方法
continue;
}
/**
* Check {@link DisableInject} to see if we need auto injection for this property
*/
if (method.getAnnotation(DisableInject.class) != null) {
//判断是否禁止注入 如果方法上明确标注了@DisableInject注解,忽略该方法
continue;
}
//根据setter方法的参数,确定扩展接口
Class<?> pt = method.getParameterTypes()[0];
//判断是否为基本类型 原始类型(boolean、char、byte、short、int、long、float、double)
//如果参数为简单类型,忽略该setter方法(略)
if (ReflectUtils.isPrimitives(pt)) {
continue;
}
try {
//setter方法注入 获取需要set的扩展点名称
String property = getSetterProperty(method);
//从扩展中获取对象 加载并实例化扩展实现类
Object object = objectFactory.getExtension(pt, property);
//从ExtensionLoader中加载指定的扩展点
//// 比如有一个方法为setRandom(LoadBalance loadBalance),那么则以为着需要加载负载均衡中名为random的扩展点
if (object != null) {
method.invoke(instance, object);
}
} catch (Exception e) {
logger.error("Failed to inject via method " + method.getName()
+ " of interface " + type.getName() + ": " + e.getMessage(), e);
}
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return instance;
}
getAdaptiveExtensionClass
private Class<?> getAdaptiveExtensionClass() {
//确保已经加载了所有的扩展类信息
getExtensionClasses();
if (cachedAdaptiveClass != null) {
//如果已经加载过了,则直接返回
return cachedAdaptiveClass;
}
//否则进行构建操作
return cachedAdaptiveClass = createAdaptiveExtensionClass();
}
获取所有的扩展类信息
private Map<String, Class<?>> getExtensionClasses() {
//从缓存中获取 ExtensionLoader 加载的扩展名与扩展实现类之间的映射关系。cachedNames 集合的反向关系缓存
Map<String, Class<?>> classes = cachedClasses.get();
if (classes == null) {
synchronized (cachedClasses) {
classes = cachedClasses.get();
if (classes == null) {
//加载配置文件
classes = loadExtensionClasses();
cachedClasses.set(classes);
}
}
}
return classes;
}
createAdaptiveExtensionClass
/**
* 生成一个 xxxx$Adaptive 适配器类
* @return
*/
private Class<?> createAdaptiveExtensionClass() {
//实例化一个新的Adaptive的代码生成器,并且进行代码生成
String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate();
//获取当前类的类加载器
ClassLoader classLoader = findClassLoader();
//通过扩展点,寻找编译器, 目前有Java自带的编译器和Javassist的编译器
org.apache.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
//编译并且生成class
return compiler.compile(code, classLoader);
}
具体通过 AdaptiveClassLoaderCodeGenerator.generate 方法来进行实现真正的代码生成
public String generate() {
// no need to generate adaptive class since there's no adaptive method found.
//如果没有任何方法标记为Adaptive,则不做处理
if (!hasAdaptiveMethod()) {
throw new IllegalStateException("No adaptive method exist on extension " + type.getName() + ", refuse to create the adaptive class!");
}
//行编写代码
StringBuilder code = new StringBuilder();
//生成包的信息
code.append(generatePackageInfo());
//生成 生成引用信息 import
code.append(generateImports());
//生成类声明
code.append(generateClassDeclaration());
//生成每一个方法
Method[] methods = type.getMethods();
for (Method method : methods) {
code.append(generateMethod(method));
}
//输出最后的一个"}"来结束当前类
code.append("}");
if (logger.isDebugEnabled()) {
logger.debug(code.toString());
}
return code.toString();
}
generateMethod
private String generateMethod(Method method) {
//方法返回类型
String methodReturnType = method.getReturnType().getCanonicalName();
//方法名称
String methodName = method.getName();
//生成方法内容
String methodContent = generateMethodContent(method);
//生成方法参数
String methodArgs = generateMethodArguments(method);
//生成方法异常
String methodThrows = generateMethodThrows(method);
//格式化为一个字符串
// public %s %s(%s) %s {
// %s
// }
return String.format(CODE_METHOD_DECLARATION, methodReturnType, methodName, methodArgs, methodThrows, methodContent);
}
generateMethodContent
private String generateMethodContent(Method method) {
//获取Adaptive注解,只支持含有Adaptive注解方法处理
Adaptive adaptiveAnnotation = method.getAnnotation(Adaptive.class);
StringBuilder code = new StringBuilder(512);
if (adaptiveAnnotation == null) {
//没有该注解,直接抛出异常
return generateUnsupported(method);
} else {
//获取URL参数的所在位置
int urlTypeIndex = getUrlTypeIndex(method);
// found parameter in URL type
//增加判断url不为空的代码
if (urlTypeIndex != -1) {
// Null Point check
code.append(generateUrlNullCheck(urlTypeIndex));
} else {
// did not find parameter in URL type
//获取这个方法中的所有参数列表
// 寻找每个参数中是否有"get"开头的方法,并且返回值是URL的
// 如果有则同样认定为找到,否则抛出异常
code.append(generateUrlAssignmentIndirectly(method));
}
//获取扩展点的适配名称
String[] value = getMethodAdaptiveValue(adaptiveAnnotation);
// 判断是否有参数是Invocation类
// 这里判断的主要目的在于,拥有Invocation时,则获取扩展名称的方式发生改变
// 存在Invocation时,通过getMethodParameter,否则通过getParameter来执行
// getMethodParameter是dubboURL中特有的,用于将"test.a"转换为"testA"的形式
boolean hasInvocation = hasInvocationArgument(method);
//增加有Invocation类时的不为空判断
code.append(generateInvocationArgumentNullCheck(method));
//生成获取扩展点名称的方法
code.append(generateExtNameAssignment(value, hasInvocation));
// check extName == null?
//检查扩展点不能为空
code.append(generateExtNameNullCheck(value));
//获取扩展点实现
code.append(generateExtensionAssignment());
//返回扩展点中的真实调用
// return statement
code.append(generateReturnAndInvocation(method));
}
return code.toString();
}
上一篇: Linux内核配置选项
下一篇: 信号究竟发给谁