首先遍历每个方法,判断存在一个方法有注释 @Adaptive,没有则抛异常。找到有注释的方法后,先找到存在 URL.class 入参的位置,生成校验 URL 入参代码。然后从 @Adaptive 的 value 属性中取值,没有的话,只能用类名小写代替,即为 “car”(这个参数是 URL 上的占位符 key,用作取数据)。然后判断方法参数列表是否有 org.apache.dubbo.rpc.Invocation 入参,有也生成相应的校验入参代码。最后根据 value 值,生成获取参数的代码,并返回
重点
@Adaptive 注解中,如果填写了 value 值,代表指定占位符名称,没填写,则用类名小写
一定要填入 URL.class 参数,除非自定义其他 protocol 协议
没标注 @Adaptive 注解的方法,使用会抛异常
可以再添加一个 org.apache.dubbo.rpc.Invocation 入参
生成的代理代码如下
packagecom.luban.dubbo_spi.api;importorg.apache.dubbo.common.extension.ExtensionLoader;publicclassCar$Adaptiveimplementscom.luban.dubbo_spi.api.Car{publicvoidgetColorForUrl(org.apache.dubbo.common.URL arg0){if(arg0 ==null)thrownewIllegalArgumentException("url == null");org.apache.dubbo.common.URL url = arg0;String extName = url.getParameter("car");if(extName ==null)thrownewIllegalStateException("Fail to get extension(com.luban.dubbo_spi.api.Car) name from url("+ url.toString()+") use keys([car])");com.luban.dubbo_spi.api.Car extension =(com.luban.dubbo_spi.api.Car)ExtensionLoader.getExtensionLoader(com.luban.dubbo_spi.api.Car.class).getExtension(extName);extension.getColorForUrl(arg0);}publicvoidgetColor(){thrownewUnsupportedOperationException("method public abstract void com.luban.dubbo_spi.api.Car.getColor() of interface com.luban.dubbo_spi.api.Car is not adaptive method!");}}
源代码
publicclassExtensionLoader<T>{privatefinalClass<?> type;privateString cachedDefaultName;...privateStringcreateAdaptiveExtensionClassCode(){StringBuilder codeBuilder =newStringBuilder();Method[] methods = type.getMethods();boolean hasAdaptiveAnnotation =false;// 1. 看是不是所有方法上都没有 Adaptive 注解,都没有则会抛异常for(Method m : methods){if(m.isAnnotationPresent(Adaptive.class)){
hasAdaptiveAnnotation =true;break;}}// 没有 Adaptive 注解,就抛异常if(!hasAdaptiveAnnotation){thrownewIllegalStateException("No adaptive method on extension "+ type.getName()+", refuse to create the adaptive class!");}// 生成包,import, 类名
codeBuilder.append("package ").append(type.getPackage().getName()).append(";");
codeBuilder.append("\nimport ").append(ExtensionLoader.class.getName()).append(";");
codeBuilder.append("\npublic class ").append(type.getSimpleName()).append("$Adaptive").append(" implements ").append(type.getCanonicalName()).append(" {");for(Method method : methods){Class<?> rt = method.getReturnType();Class<?>[] pts = method.getParameterTypes();Class<?>[] ets = method.getExceptionTypes();Adaptive adaptiveAnnotation = method.getAnnotation(Adaptive.class);StringBuilder code =newStringBuilder(512);// 2. 如果方法上没有 Adaptive 注解,则加上抛异常代码if(adaptiveAnnotation ==null){
code.append("throw new UnsupportedOperationException(\"method ").append(method.toString()).append(" of interface ").append(type.getName()).append(" is not adaptive method!\");");}else{// 3. 寻找 URL 参数所在位置int urlTypeIndex =-1;for(int i =0; i < pts.length;++i){if(pts[i].equals(URL.class)){
urlTypeIndex = i;break;}}// 4. 存在 URL 参数,就从 URL 中取数据,并判空if(urlTypeIndex !=-1){// Null Point checkString s =String.format("\nif (arg%d == null) throw new IllegalArgumentException(\"url == null\");",
urlTypeIndex);
code.append(s);
s =String.format("\n%s url = arg%d;",URL.class.getName(), urlTypeIndex);
code.append(s);}else{String attribMethod =null;// 如果没有 URL 参数,就从其他参数中去找是不是有返回值为 URL 的 get 方法LBL_PTS:for(int i =0; i < pts.length;++i){Method[] ms = pts[i].getMethods();for(Method m : ms){String name = m.getName();if((name.startsWith("get")|| name.length()>3)&&Modifier.isPublic(m.getModifiers())&&!Modifier.isStatic(m.getModifiers())&& m.getParameterTypes().length ==0&& m.getReturnType()==URL.class){
urlTypeIndex = i;
attribMethod = name;breakLBL_PTS;}}}if(attribMethod ==null){thrownewIllegalStateException("fail to create adaptive class for interface "+ type.getName()+": not found url parameter or url attribute in parameters of method "+ method.getName());}// Null point checkString s =String.format("\nif (arg%d == null) throw new IllegalArgumentException(\"%s argument == null\");",
urlTypeIndex, pts[urlTypeIndex].getName());
code.append(s);
s =String.format("\nif (arg%d.%s() == null) throw new IllegalArgumentException(\"%s argument %s() == null\");",
urlTypeIndex, attribMethod, pts[urlTypeIndex].getName(), attribMethod);
code.append(s);
s =String.format("%s url = arg%d.%s();",URL.class.getName(), urlTypeIndex, attribMethod);
code.append(s);}// 5. 取 adaptive 注解的值,可以是个数组,如果没有值,则会取类名,LoadBalance->load.balanceString[] value = adaptiveAnnotation.value();if(value.length ==0){String splitName =StringUtils.camelToSplitName(type.getSimpleName(),".");
value =newString[]{splitName};}// 6. 判断参数列表中是否有 Invocation 对象boolean hasInvocation =false;for(int i =0; i < pts.length;++i){if(("org.apache.dubbo.rpc.Invocation").equals(pts[i].getName())){// Null Point checkString s =String.format("\nif (arg%d == null) throw new IllegalArgumentException(\"invocation == null\");", i);
code.append(s);
s =String.format("\nString methodName = arg%d.getMethodName();", i);
code.append(s);
hasInvocation =true;break;}}// 默认名是接口上的 Extension 注解上对于的值String defaultExtName = cachedDefaultName;String getNameCode =null;// 倒序循环 adaptive 注解的值for(int i = value.length -1; i >=0;--i){if(i == value.length -1){if(null!= defaultExtName){if(!"protocol".equals(value[i])){if(hasInvocation){// url.getMethodParameter(methodName, value[i], defaultExtName)// methodName 是从 Invocation 对象中获取的
getNameCode =String.format("url.getMethodParameter(methodName, \"%s\", \"%s\")", value[i], defaultExtName);}else{// url.getParameter(value[i], defaultExtName)
getNameCode =String.format("url.getParameter(\"%s\", \"%s\")", value[i], defaultExtName);}}else{
getNameCode =String.format("( url.getProtocol() == null ? \"%s\" : url.getProtocol() )", defaultExtName);}}else{if(!"protocol".equals(value[i])){if(hasInvocation){
getNameCode =String.format("url.getMethodParameter(methodName, \"%s\", \"%s\")", value[i], defaultExtName);}else{
getNameCode =String.format("url.getParameter(\"%s\")", value[i]);}}else{
getNameCode ="url.getProtocol()";}}}else{if(!"protocol".equals(value[i])){if(hasInvocation){
getNameCode =String.format("url.getMethodParameter(methodName, \"%s\", \"%s\")", value[i], defaultExtName);}else{// 7. 生成取从 URL 取数据代码,其中 value[i] = car
getNameCode =String.format("url.getParameter(\"%s\", %s)", value[i], getNameCode);}}else{
getNameCode =String.format("url.getProtocol() == null ? (%s) : url.getProtocol()", getNameCode);}}}
code.append("\nString extName = ").append(getNameCode).append(";");// check extName == null?String s =String.format("\nif(extName == null) "+"throw new IllegalStateException(\"Fail to get extension(%s) name from url(\" + url.toString() + \") use keys(%s)\");",
type.getName(),Arrays.toString(value));
code.append(s);// 根据取出来的扩展名获取扩展
s =String.format("\n%s extension = (%<s)%s.getExtensionLoader(%s.class).getExtension(extName);",
type.getName(),ExtensionLoader.class.getSimpleName(), type.getName());
code.append(s);// return statementif(!rt.equals(void.class)){
code.append("\nreturn ");}// 执行扩展实现类的方法
s =String.format("extension.%s(", method.getName());
code.append(s);for(int i =0; i < pts.length; i++){if(i !=0){
code.append(", ");}
code.append("arg").append(i);}
code.append(");");}
codeBuilder.append("\npublic ").append(rt.getCanonicalName()).append(" ").append(method.getName()).append("(");for(int i =0; i < pts.length; i++){if(i >0){
codeBuilder.append(", ");}
codeBuilder.append(pts[i].getCanonicalName());
codeBuilder.append(" ");
codeBuilder.append("arg").append(i);}
codeBuilder.append(")");if(ets.length >0){
codeBuilder.append(" throws ");for(int i =0; i < ets.length; i++){if(i >0){
codeBuilder.append(", ");}
codeBuilder.append(ets[i].getCanonicalName());}}
codeBuilder.append(" {");
codeBuilder.append(code.toString());
codeBuilder.append("\n}");}
codeBuilder.append("\n}");if(logger.isDebugEnabled()){
logger.debug(codeBuilder.toString());}// 8. 返回生成的代码return codeBuilder.toString();}}
packagecom.luban.dubbo_spi.api;importorg.apache.dubbo.common.extension.ExtensionLoader;publicclassCar$Adaptiveimplementscom.luban.dubbo_spi.api.Car{publicvoidgetColorForUrl(org.apache.dubbo.common.URL arg0){if(arg0 ==null)thrownewIllegalArgumentException("url == null");org.apache.dubbo.common.URL url = arg0;String extName = url.getParameter("car");if(extName ==null)thrownewIllegalStateException("Fail to get extension(com.luban.dubbo_spi.api.Car) name from url("+ url.toString()+") use keys([car])");com.luban.dubbo_spi.api.Car extension =(com.luban.dubbo_spi.api.Car)ExtensionLoader.getExtensionLoader(com.luban.dubbo_spi.api.Car.class).getExtension(extName);extension.getColorForUrl(arg0);}publicvoidgetColor(){thrownewUnsupportedOperationException("method public abstract void com.luban.dubbo_spi.api.Car.getColor() of interface com.luban.dubbo_spi.api.Car is not adaptive method!");}}
【问题描述】:pycharm中运行py文件时,报错:找不到自己编写的包等目录问题
【报错】: ModuleNotFoundError: No module named ‘xxx’ ERROR: file not found
【问题定位】:运行的py文件和用到的包或者数据不在同一个文件目录下时…
写在前面:本博客仅作记录学习之用,部分图片来自网络,如需引用请注明出处,同时如有侵犯您的权益,请联系删除! 文章目录 前言试用步骤问题No CUDA GPUs are available无故被killed 致谢 前言
算力在深度学习…