Java-马士兵设计模式学习笔记-代理模式-动态代理 调用Proxy.newProxyInstance()
阅读原文时间:2024年06月14日阅读:1

一、概述

1.目标:不自己写代理类,利用Proxy.newProxyInstance()动态生成

2.用到的知识点:

(1)//编译源码,生成class,注意编译环境要换成jdk才有compiler,单纯的jre没有compiler,会空指针错误

JavaCompiler jc = ToolProvider.getSystemJavaCompiler();

(2)//文件管事器
StandardJavaFileManager fileMgr = jc.getStandardFileManager(null, null, null);

(3)//编译单元
Iterable units = fileMgr.getJavaFileObjects(file);

(4)//编译任务
CompilationTask t = jc.getTask(null, fileMgr, null, null, null, units);

(5)//编译
t.call();

(6)//把类load到内存里

URL[] urls = new URL[] {new URL("file:/"+System.getProperty("user.dir")+"/src/proxy/TankTimeProxy.class")};
URLClassLoader uc = new URLClassLoader(urls);
Class c = uc.loadClass("proxy.TankTimeProxy");

(7)//生成实例

//return c.newInstance(); //c.newInstance()会调用无参数的Construtor,若类没有无参的Constructor时会出错
Constructor ctr = c.getConstructor(Movable.class);
return ctr.newInstance(new Tank());

二、代码

1.Movable.java

2.Tank.java

3.Proxy.java

4.Client.java

1.Movable.java

package proxy;

public interface Movable {
public void move();
}

2.Tank.java

package proxy;

import java.util.Random;

public class Tank implements Movable {

@Override  
public void move() {  
    System.out.println("Tank moving.......");  
    try {  
        Thread.sleep(new Random().nextInt(2000));  
    } catch (InterruptedException e) {  
        e.printStackTrace();  
    }  
}

}

3.Proxy.java

package proxy;

import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.net.URLClassLoader;

import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

public class Proxy {

 public static Object newProxyInstance() throws Exception {  
     String rt = "\\n\\r";

     //动态代理文件的源码  
     String str =  
     "package proxy;" + rt +

     "public class TankTimeProxy implements Movable {"+rt+

         "private Movable m;" + rt +

         "public TankTimeProxy(Movable m) {" + rt +  
             "this.m = m;" + rt +  
         "}" + rt +

         "@Override" + rt +  
         "public void move() {" + rt +  
             "System.out.println(\\"Time Proxy start...........\\");" + rt +  
             "long start = System.currentTimeMillis();" + rt +  
             "m.move();" + rt +  
             "long end = System.currentTimeMillis();" + rt +  
             "System.out.println(\\"花费时间:\\"+(end - start));" + rt +  
             "System.out.println(\\"Time Proxy end...........\\");" + rt +  
         "}" + rt +

     "}" ;

     //把源码写到java文件里  
     File file = new File(System.getProperty("user.dir")+"/src/proxy/TankTimeProxy.java");  
     FileWriter fw = new FileWriter(file);  
     fw.write(str);  
     fw.flush();  
     fw.close();

     //编译源码,生成class,注意编译环境要换成jdk才有compiler,单纯的jre没有compiler,会空指针错误  
     JavaCompiler jc = ToolProvider.getSystemJavaCompiler();

     //文件管事器  
     StandardJavaFileManager fileMgr = jc.getStandardFileManager(null, null, null);

     //编译单元  
     Iterable units = fileMgr.getJavaFileObjects(file);

     //编译任务  
     CompilationTask t = jc.getTask(null, fileMgr, null, null, null, units);

     //编译  
     t.call();  
     fileMgr.close();

     //把类load到内存里  
     URL\[\] urls = new URL\[\] {new URL("file:/"+System.getProperty("user.dir")+"/src/proxy/TankTimeProxy.class")};  
     URLClassLoader uc = new URLClassLoader(urls);  
     Class c = uc.loadClass("proxy.TankTimeProxy");

     //生成实例  
     //return c.newInstance(); //c.newInstance()会调用无参数的Construtor,若类没有无参的Constructor时会出错  
     Constructor ctr = c.getConstructor(Movable.class);  
     return ctr.newInstance(new Tank());  
 }  

}

4.Client.java

package proxy;

import java.io.IOException;

import org.junit.Test;

public class Client {

 @Test  
 public void testProxy() throws Exception{

     Movable m = (Movable)Proxy.newProxyInstance();  
     m.move();

 }  

}

三、运行结果