- /*
- * 接口中有几个方法,那么使用反射的getMethods()就会有几个方法名
- * 因为接口是不会继承Object的
- */
- public interface Moveable {
- void move();//
- }
- public class Car implements Moveable{
- @Override
- public void move() {
- System.out.println("我是卡车,出发开往目的地...");
- }
- }
- public interface UserMgr {
- void addUser();
- }
- public class UserMgrImpl implements UserMgr {
- @Override
- public void addUser() {
- System.out.println("1: 插入记录到user表");
- System.out.println("2: 做日志在另外一张表");
- }
- }
- //作为动态代理的预设框架,把需要增加的内容放入事先写好的功能中
- public interface InvocationHandler {
- /**
- * @param obj 要代理类的对象car
- * @param method 要代理类的对象car的代理方法
- */
- void invoke(Object obj,Method method);
- }
- //对要代理类的对象的方法进行运行时间长短的测量
- public class TimerInvocation implements InvocationHandler{
- //target是要代理的对象,在客户端创建TimeInvocation时就进行传递
- //为什么不在下面的invoke里直接传递obj为要代理的对象呢?
- //那是因为在Proxy1类中要创建一个临时的代理对象$Proxy,然后这个$Proxy
- //的对象会会调用这个TimerInvocation中的invoke方法,这个时候无法传递真
- //正的要代理的对象,使用反射也不行,因为反射只会创建一个新的实例,而非一
- //个拥有某种属性或功能的对象,故只能在客户端中进行传递
- private Object target;
- public TimerInvocation(Object target){
- this.target=target;
- }
- //method是要代理的对象的方法
- //这里的obj暂时没起到作用
- @Override
- public void invoke(Object obj, Method method) {
- System.out.println("开始进行运行时间测量...");
- long start=System.currentTimeMillis();
- try {
- method.invoke(target);
- } catch (Exception e) {
- e.printStackTrace();
- }
- System.out.println("共耗费时间:"+(System.currentTimeMillis()-start));
- }
- }
- public class TransactionHandler implements InvocationHandler {
- private Object target;
- public TransactionHandler(Object target) {
- super();
- this.target = target;
- }
- @Override
- public void invoke(Object o, Method m) {
- System.out.println("Transaction Start");
- try {
- m.invoke(target);
- } catch (Exception e) {
- e.printStackTrace();
- }
- System.out.println("Transaction Commit");
- }
- }
- public class Proxy1 {
- /**
- *
- * @param interfa 这个就是Moveable接口的class
- * @param h 告诉Proxy类要产生的是什么类型的代理,可以是时间代理,日志代理
- * 也就是要对interfa里的方法实现什么样的代理或功能
- * @return
- * 思路:
- * 生成一个临时的代理类$Proxy,这个类继承于Moveable接口
- * 这个类要去调用InvacationHandler的子类的invoke方法,实现切面的功能
- * 然后返回这个临时代理类的对象,并让得到这个代理类的对象调用move()方法即可
- */
- public static Object newProxyInstance(Class interfa,InvocationHandler h)throws Exception{
- String rt="\r\n";
- String java="package proxy1.dynamic;" + rt ;
- java+="import java.lang.reflect.Method;" + rt ;
- java+="public class $Proxy implements "+interfa.getName() +"{" + rt;
- java+=" private InvocationHandler hand;" + rt;
- java+=" public $Proxy(InvocationHandler hand){" + rt;
- java+=" this.hand=hand;" + rt;
- java+=" }" + rt;
- Method[] methods=interfa.getMethods();
- for(Method method : methods){//对接口interfa中的方法进行实现
- java+=" @Override" + rt;
- java+=" public void "+method.getName()+"(){" + rt;
- java+=" try{" + rt;
- java+=" Method m="+interfa.getName()+".class.getMethod(\""+method.getName()+"\");" + rt;
- java+=" hand.invoke(this,m);" + rt;
- java+=" }catch(Exception e){e.printStackTrace();}" + rt;
- java+=" }" + rt;
- }
- java+="}" + rt;
- System.out.println(java);
- //创建java文件
- String filepath=System.getProperty("user.dir")+"/src/proxy1/dynamic";
- File file=new File(filepath+"/$Proxy.java");
- try{
- file.createNewFile();
- FileWriter fw=new FileWriter(file);
- fw.write(java);
- fw.close();
- }catch(Exception e){e.printStackTrace();}
- //编译
- JavaCompiler javac=ToolProvider.getSystemJavaCompiler();
- StandardJavaFileManager javafile=javac.getStandardFileManager(null, null, null);
- String filename=filepath+"/$Proxy.java";
- Iterable units=javafile.getJavaFileObjects(filename);
- CompilationTask t=javac.getTask(null, javafile, null, null, null, units);
- t.call();
- try {javafile.close();
- } catch (IOException e) {e.printStackTrace();}
- //把刚才在D:/下生成的class文件CarTimeProxy.class加载进内存并生成实例对象
- URL[] urls;
- Object obj=null;
- try {
- urls = new URL[]{new URL("file:///D:/Workspaces/base/bin/")};
- URLClassLoader classload=new URLClassLoader(urls);
- Class clazz=classload.loadClass("proxy1.dynamic.$Proxy");
- Constructor cons=clazz.getConstructor(InvocationHandler.class);
- obj=cons.newInstance(h);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return obj;
- }
- }
- public class Client {
- public static void main(String[] args) throws Exception {
- /*Moveable move=new Car();
- Moveable proxy=(Moveable) Proxy.newProxyInstance(move);
- proxy.move();*/
- /*Moveable move=new Car();
- InvocationHandler hand=new TimerInvocation(move);
- Moveable proxy=(Moveable)Proxy1.newProxyInstance(Moveable.class, hand);
- proxy.move();*/
- UserMgr mgr = new UserMgrImpl();
- InvocationHandler h = new TransactionHandler(mgr);//先对日志进行捕获
- UserMgr u = (UserMgr)Proxy1.newProxyInstance(UserMgr.class,h);
- InvocationHandler h2 = new TimerInvocation(u);//再对时间进行测量
- UserMgr u1 = (UserMgr)Proxy1.newProxyInstance(UserMgr.class,h2);
- u1.addUser();
- /**
- * 运行结果:
- * 开始进行运行时间测量...
- * Transaction Start
- * 1: 插入记录到user表
- * 2: 做日志在另外一张表
- * Transaction Commit
- * 共耗费时间:0
- */
- }
- }