动态代理是很多框架都在使用的技术,现在不少框架的类动态生成使用的是cglib,最近想起jdk1.6开放了类的编译api尝试做了个demo。
一.类的动态生成方式:
1.使用编译时注解,编译时生成.java文件,让jdk编译为class
2.使用字符串拼接代码,cglib生成.class文件
3.使用字符串拼接成代码,JavaCompiler生成class文件
二.JavaCompiler实际使用
1.生成动态代码,这里为了简便直接拼装一个class出来,为了验证实现接口也能编译出来,我加上了一个接口。
public static String getClassJava() {
StringBuilder builder = new StringBuilder("package com.xsq.test");
builder.append(";import com.xsq.test.compiler.TestInte;");
builder.append("public class TestLoadClass implements TestInte{ public void test(){ System.out.println(\"我就是一个测试78789798798\"); } }");
return builder.toString();
}
2.有了代码我们就需要编译代码,这里有2种方式,(1)写出文件,从文件编译;(2)直接在内存编译,我们拼接的class本来就在内存,没必要写出再加载浪费时间和空间,所以直接从内存编译
1)JavaCompiler编译时需要一个JavaFileObject和一个StandardJavaFileManager,系统的JavaFileObject都是针对文件的,这里我们先自定义一个针对Str的JavaFileObject
/**
* 描述:
* 自定义String字符串对象文件处理
*
* @author XiangQingSong
* @create 2020-01-08-15:32
*/
public class StrSrcJavaObject extends SimpleJavaFileObject{
/**str拼接的类*/
private String content;
/**类名*/
private String name;
/**编译后的文件内容*/
private final Map<String, byte[]> clam = new HashMap<String, byte[]>();
/**
*
*/
public StrSrcJavaObject(String name, String count) {
super(URI.create("string:///" + name.replace(".", "/") + Kind.SOURCE.extension), Kind.SOURCE);
this.content = count;
this.name = name;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
System.out.println("获取拼接类" + content);
return content;
}
@Override
public OutputStream openOutputStream() throws IOException {
System.out.