javassist
Javassist是一款字节码编辑工具,可以直接编辑和生成Java生成的字节码,以达到对.class文件进行动态修改的效果。熟练使用这套工具,可以让Java编程更接近与动态语言编程。
maven依赖
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.20.0-GA</version>
</dependency>
API讲解
/**
* Javassist测试类
* @author yangyanping
* @date 2021-07-28
*/
public class JavassistTest {
public static void main(String[] args) throws Exception {
//初始化 javassist 的类池
ClassPool pool = ClassPool.getDefault();
// 创建一个Hello 类
CtClass ctClass = pool.makeClass("com.jd.Hello");
// 添加一个ID属性
CtField idField = new CtField(CtClass.longType, "id", ctClass);
ctClass.addField(idField);
// 添加一个test 方法
CtMethod ctMethod = CtNewMethod.make("public static void test() {System.out.println(\"Hello World !\");}",ctClass);
ctClass.addMethod(ctMethod);
//生成类
Class<?> clazz = ctClass.toClass();
//创建实例
Object obj = clazz.newInstance();
Method method = clazz.getDeclaredMethod("test",null);
method.invoke(obj,null);
}
}
运行结果:
Hello World !
自适应加载机制
为 Dubbo 更加灵活的使一个接口不通过硬编码加载扩展机制,而是通过使用过程中进行加载,Dubbo 的另一加载机制——自适应加载。
自适应加载机制使用 @Adaptive 标注:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Adaptive {
String[] value() default {};
}
@Adaptive 注解使用
/**
* 水果 接口
* @author yangyanping
* @date 2021-07-30
*/
@SPI("apple")
public interface Fruit {
@Adaptive("adaptiveTest")
String echo(URL url);
}
Apple 实现类
public class Apple implements Fruit {
@Override
public String echo(URL url) {
return "Apple";
}
}
Banlana 实现类
public class Banlana implements Fruit {
@Override
public String echo(URL url) {
return "banana";
}
}
AdaptiveTest 单元测试类
public class AdaptiveTest {
@Test
public void testGenerator() {
URL url = URL.valueOf("dubbo://localhost:8082?adaptiveTest=apple");
String msg = ExtensionLoader.getExtensionLoader(Fruit.class).getAdaptiveExtension().echo(url);
System.out.println(msg);
url = URL.valueOf("dubbo://localhost:8082?adaptiveTest=banana");
msg = ExtensionLoader.getExtensionLoader(Fruit.class).getAdaptiveExtension().echo(url);
System.out.println(msg);
url = URL.valueOf("dubbo://localhost:8082");
msg = ExtensionLoader.getExtensionLoader(Fruit.class).getAdaptiveExtension().echo(url);
System.out.println(msg);
}
}
运行结果:
Apple
banana
Apple
Fruit$Adaptive 代理类
package com.jd.dubbo.adaptive;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
public class Fruit$Adaptive implements com.jd.dubbo.adaptive.Fruit {
public java.lang.String echo(com.alibaba.dubbo.common.URL arg0) {
if (arg0 == null) throw new IllegalArgumentException("url == null");
com.alibaba.dubbo.common.URL url = arg0;
String extName = url.getParameter("adaptiveTest", "apple");
if (extName == null)
throw new IllegalStateException("Fail to get extension(com.jd.dubbo.adaptive.Fruit) name from url(" + url.toString() + ") use keys([adaptiveTest])");
com.jd.dubbo.adaptive.Fruit extension = (com.jd.dubbo.adaptive.Fruit) ExtensionLoader.getExtensionLoader(com.jd.dubbo.adaptive.Fruit.class).getExtension(extName);
return extension.echo(arg0);
}
}
创建扩展到对象
private Class<?> createAdaptiveExtensionClass() {
// 生成自适应扩展代码
String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate();
// 获取扩展类加载器
ClassLoader classLoader = findClassLoader();
// 获取编译器类型的实现类
org.apache.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
// 编译代码,返回该对象
return compiler.compile(code, classLoader);
}