设计模式之代理模式(2)

前一篇文章提到了是静态代理,其实用聚合的方式实现代理,当需求过多的时候,也会发生类爆发。

所以上有政策,下有对策嘛!可以把所有的代理放在一个代理类中Proxy类中,Proxy被称为总代理!由总代理实现动态代理!

要说的东西有点多,先上个代码把!

Proxy.java(总代理)

package cn.asto.proxy;

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 Moveable getProxyInstance() throws Exception{
        String rt ="\r\t";
        String str =
        "package cn.asto.proxy;"+ rt +

        "public class TankTimeProxy implements Moveable {"+ rt +

        "    private Moveable t;"+ rt +
            
            
        "    public TankTimeProxy(Moveable t) {"+ rt +
        "        super();"+ rt +
        "        this.t = t;"+ rt +
        "}"+ rt +

        "    @Override"+ rt +
        "    public void move() {"+ rt +
        "        long startTime = System.currentTimeMillis();"+ rt +
        "        System.out.println(\"startTime:\"+startTime);"+ rt +
        "        t.move();"+ rt +
        "        long endTime = System.currentTimeMillis();"+ rt +
        "        System.out.println(\"Time:\"+(endTime-startTime));"+ rt +

        "    }"+ rt +


        "}";
        String fileName =System.getProperty("user.dir")+"/src/cn/asto/proxy/TankTimeProxy.java";
        FileWriter fw = new FileWriter(fileName);
        fw.write(str);
        fw.flush();
        fw.close();
        //compile
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);
        Iterable units = fileMgr.getJavaFileObjects(fileName);
        CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units);
        t.call();
        fileMgr.close();
        
        //load into memory and create an instance
        URL[] urls = new URL[]{(new URL("file:/"+System.getProperty("user.dir")+"/src"))};
        URLClassLoader ul = new URLClassLoader(urls);
        Class c = ul.loadClass("cn.asto.proxy.TankTimeProxy");
        System.out.println(c);
        Constructor ctr = c.getConstructor(Moveable.class);
        Moveable m = (Moveable)ctr.newInstance(new Tank());
        return m;
    }
}

Test1.java

package cn.asto.compiler.test;

import cn.asto.proxy.Moveable;
import cn.asto.proxy.Proxy;

public class Test1 {

    public static void main(String args[]) throws Exception{
        Moveable m = Proxy.getProxyInstance();
        m.move();
    }
}

我的目录结构:

 

下面开始我的BB:

动态代理解决了静态代理的类爆炸问题,因为不需要写代理类,代理类动态生成。

先将str通过字符流写入文件,再通过jdk自带的工具进行编译,加载到jvm里面,然后利用java的反射机制生成对象。

本质上来说,其实就是通过动态加载类,减少了静态代理类的编写。就这么简单!

好,我的BB结束了!

posted @ 2015-08-17 18:50  陈其苗  阅读(373)  评论(0编辑  收藏  举报