此时已经生成java文件,还需要进行动态的编译生成的代理类。
首先需要获取当前系统的java编译器:
【a】JavaCompiler compiler=ToolProvider.getSystemJavaCompiler();
创建文件的管理者:
【b】StandardJavaFileManager fileMgr=compiler.getStandardFileManager(diagnosticListener,locale,charset),该方法的第一个参数是扫描监听器,第二个和第三个都是国际化参数,这里为了简单起见都设置为null。

根据文件的路径来得到管理文件的数组:
【c】Iterable units=fileMgr.getJavaFileObjects(filename);
获取编译的任务:
【d】CompilationTask t=complier.getTask(null,fileMgr,null,null,null,units),第一个参数是输出的位置,这里使用null。第二个参数是文件管理者。第三个参数是监听器。第四个和第五个参数是国际化参数这里都设置为null。第六个参数是要编译的文件,该方法返回的是编译的任务。

接下来进行编译:
【5】t.call();
最后把文件管理者关闭掉:
【6】eMgr.close();

这样就可以对生成的$Proxy0进行编译(产生$Proxy0.class,说明编译成功,如图)。

【3】将这个类加载到内存当中,产生一个新的对象(该对象就是代理对象)。
因为生成的文件是在指定的目录下,可以通过ClassLoader进行加载:
【a】获取类加载器:ClassLoader cl=ClassLoader.getSystemClassLoader();
通过类加载器加载文件:
【b】Class c=cl.loadClass("com.imooc.proxy.$Proxy0");参数是相对路径。这里为了验证可以通过c.getName()把加载的类名输出。

这样就会把代理类加载到内存当中。
【4】return该代理对象。
产生代理对象并进行返回,创建代理类可以通过构造器进行初始化,根据构造器方法传递的参数来创建该对象(构造器中传递的是接口实现类的对象):
Constructor ctr=c.getConstructor(infce);
根据构造器创建代理对象:
ctr.newInstance(new Car());

这样就创建了动态代理类。
测试:

完善动态代理实现 首先得到系统编译器,通过编译器得到文件管理者,以获取文件,然后编译器执行编译任务,完成编译之后,将class文件加载到类加载器中,通过构造方法得到实例,然后调用newInstance()接收一个对象的实例并返回。 (1)拿到编译器 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); (2)文件管理者 StandardJavaFileManager fileMgr = Compiler.getStandardFileManager(null,null,null); (3)获取文件 Iterable units = fileMgr.getJavaFileObjects(filename); (4)编译任务 CompilationTask t =compiler.getTask(null,fileMgr,null,null,null,units); (5)load到内存 ClassLoader cl = ClassLoader.getSystemClassLoader(); Class c = cl.loadClass(”com.imooc.proxy.$Proxy0”); (6)通过代理对象的构造器构造实例,并返回代理对象 Constructor ctr = c.getConstructor(infce); return ctr.newInstance(new Car());
//先生成java文件,然后编译
//第一种方式要编译的java文件放在文件编译路径下
//String fileName = System.getProperty("user.dir") + "/out/production/design-pattern/proxy/staticproxy/$Proxy0.java";//第二种方式:指定文件编译路径到当前项目编译路径下
//编译任务
String compilerPath = System.getProperty("user.dir") + "/out/production/design-pattern/";
//如果不传入写出路径,默认和。java文件路径相同
/**
* 编译选项,在编译java文件时,编译程序会自动的去寻找java文件引用的其他的java源文件或者class。
* -sourcepath选项就是定义java源文件的查找目录, -classpath选项就是定义class文件的查找目录,
* -d就是编译文件的输出目录。
*/
Iterable<String> options = Arrays.asList("-d", compilerPath);
JavaCompiler.CompilationTask t = compiler.getTask(null,fileMgr,null,options,null,units);//loadClass默认是在代码编译路径下,找proxy.staticproxy.$Proxy0
ClassLoader cl = ClassLoader.getSystemClassLoader();
Class c = cl.loadClass("proxy.staticproxy.$Proxy0");
System.out.println(c.getName());
完善动态代理实现 首先得到系统编译器,通过编译器得到文件管理者,以获取文件,然后编译器执行编译任务,完成编译之后,将class文件加载到类加载器中,通过构造方法得到实例,然后调用newInstance()接收一个对象的实例并返回。 (1)拿到编译器 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); (2)文件管理者 StandardJavaFileManager fileMgr = Compiler.getStandardFileManager(null,null,null); (3)获取文件 Iterable units = fileMgr.getJavaFileObjects(filename); (4)编译任务 CompilationTask t =compiler.getTask(null,fileMgr,null,null,null,units); (5)load到内存 ClassLoader cl = ClassLoader.getSystemClassLoader(); Class c = cl.loadClass(”com.imooc.proxy.$Proxy0”); (6)通过代理对象的构造器构造实例,并返回代理对象 Constructor ctr = c.getConstructor(infce); return ctr.newInstance(new Car());
类的编译,加载,构造流程很熟悉
Mark