java设计模式:代理模式

来源:互联网 发布:java怎样输出数组 编辑:程序博客网 时间:2024/06/05 23:43

代理模式

定义:为其他对象提供一种代理以控制对这个对象的访问。代理对象起到中介作用,可去掉功能服务或增加额外的服务。


平时讲的代理主要指的是智能引用代理,它又有两种实现方式:静态代理和动态代理。

静态代理:

代理和被代理对象在代理之前是确定的,他们都继承相同的抽象类或实现相同的接口。且一般都是使用聚合的方式来实现。

moveable接口

public interface Moveable {void move();}

Car类

public class Car implements Moveable {@Overridepublic void move() {try {Thread.sleep(new Random().nextInt(1000));System.out.println("汽车行驶中.....");} catch (InterruptedException e) {e.printStackTrace();}}}

TimeProxy记录行驶时间代理类

public class TimeProxy implements Moveable {private Moveable car;public TimeProxy(Moveable car) {super();this.car = car;}@Overridepublic void move() {long startime=System.currentTimeMillis();System.out.println("汽车开始行驶");car.move();long endtime=System.currentTimeMillis();System.out.println("汽车结束行驶,行驶时间:"+(endtime-startime)+"毫秒");}}

LogProxy记录日志代理类

public class LogProxy implements Moveable {private Moveable car;public LogProxy(Moveable car) {super();this.car = car;}@Overridepublic void move() {System.out.println("开始记录日志");car.move();System.out.println("日志记录结束");}}

测试类

public class Client {public static void main(String[] args) {//使用聚合的方式实现的静态代理Car car=new Car();Moveable mt=new LogProxy(car);Moveable m=new TimeProxy(mt);m.move();}}
运行结果




JDK动态代理:只能代理实现了接口的类。

TimeHandler类(实现InvocationHandler接口)

public class TimeHandler implements InvocationHandler {private Object target;public TimeHandler(Object target) {this.target=target;}/* * 参数: * proxy被代理对象 * method被代理对象的方法 * args方法的参数 *  * 返回值: * Object  方法的返回值 */@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {long startime=System.currentTimeMillis();System.out.println("汽车开始行驶");method.invoke(target);long endtime=System.currentTimeMillis();System.out.println("汽车结束行驶,行驶时间:"+(endtime-startime)+"毫秒");return null;}}

测试类

public class Test {//JDK动态代理测试类public static void main(String[] args) {Car car=new Car();InvocationHandler h=new TimeHandler(car);Class<?> cls=car.getClass();/* * loader:类加载器 * interfaces:被代理类实现的接口 * h:InvocationHandler对象(事务处理器) */Moveable m=(Moveable)Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), h); //生成代理对象m.move();}}





CGLIB动态代理:1.针对类来实现代理  2.对指定目标类产生一个子类,通过方法拦截技术拦截所有父类方法的调用。

首先你需要引入cglib-nodep-2.2.jar包

被代理类

public class Plane {public void move(){System.out.println("飞机飞行中......");}}


CglibProxy类

public class CglibProxy implements MethodInterceptor {private Enhancer enhancer=new Enhancer();//返回代理类对象public Object getProxy(Class<?> cls){//为cls创建子类代理类enhancer.setSuperclass(cls);enhancer.setCallback(this);return enhancer.create();}/* * 拦截所有目标类方法的调用 * 参数: * obj   目标类的实例 * m     目标方法的反射对象 * args  方法的参数 * proxy 代理类的实例 */@Overridepublic Object intercept(Object obj, Method m, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("日志开始..");//代理类调用父类的方法proxy.invokeSuper(obj, args);System.out.println("日志结束...");return null;}}


测试类

public class Client {public static void main(String[] args) {CglibProxy proxy=new CglibProxy();Plane p=(Plane) proxy.getProxy(Plane.class);p.move();}}





JDK动态代理实现原理:

实现功能:通过Proxy的newProxyInstance方法返回代理对象
步骤:1.声明一段源码(动态产生代理)    2.编译源码(JDK Compiler API),产生新的类(代理类)     3.将此类load到内存中,产生一个新的对象(代理对象)    4.return代理对象
下面的代码是我在之前静态代理的基础上修改的。

Car类

public class Car implements Moveable {@Overridepublic void move() {try {Thread.sleep(new Random().nextInt(1000));System.out.println("汽车行驶中.....");} catch (InterruptedException e) {e.printStackTrace();}}}

接口

public interface Moveable {void move();}

自定义的InvocationHandler接口

public interface InvocationHandler {public void invoke(Object obj,Method m);}
因为move方法没有参数,这里invoke的参数也就没加上"方法的参数"

TimeHandler类

public class TimeHandler implements InvocationHandler {private Object target;public TimeHandler(Object target) {super();this.target = target;}@Overridepublic void invoke(Object obj, Method m) {try {long startime=System.currentTimeMillis();System.out.println("汽车开始行驶");m.invoke(target);long endtime=System.currentTimeMillis();System.out.println("汽车结束行驶,行驶时间:"+(endtime-startime)+"毫秒");} catch (Exception e) {e.printStackTrace();}}}


最重要的Proxy类

public class Proxy {//infce为接口的Class对象public static Object newProxyInstance(Class infce,InvocationHandler h) throws Exception{String rt="\r\n";     //windows换行符String methodStr="";for(Method m:infce.getMethods()){methodStr+="    @Override"+rt+"public void "+m.getName()+"() {"+rt+"      try{"+rt+" Method md="+infce.getName()+".class.getMethod(\""+m.getName()+"\");"+rt+    "        h.invoke(this,md);"+rt+    "      }catch(Exception e){e.printStackTrace();}"+rt+"}";}//1.声明一段源码String str="package com.wulijian.staticproxy;"+rt+"import com.wulijian.staticproxy.InvocationHandler;"+rt+"import java.lang.reflect.Method;"+rt+"public class $Proxy0 implements "+infce.getName()+"{"+rt+     //jdk生成的动态代理类名字是$Proxy0"    private InvocationHandler h;"+rt+" public $Proxy0(InvocationHandler h) {"+rt+"        this.h = h;"+rt+"    }"+rt+methodStr+rt+"}";//2.编译源码,产生代理类//String filename=System.getProperty("user.dir");   当前工程所在路径(F:\eclipse_workspace\Proxy)String filename=System.getProperty("user.dir")+"/bin/com/wulijian/staticproxy/$Proxy0.java";    File file=new File(filename);        FileUtils.writeStringToFile(file, str);    //得到编译器    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);        //进行编译,生成.class文件    t.call();        fileMgr.close();            //3.将class文件load到内存中    ClassLoader cl=ClassLoader.getSystemClassLoader();    Class c=cl.loadClass("com.wulijian.staticproxy.$Proxy0");        Constructor ctr=c.getConstructor(InvocationHandler.class);    //得到反射类实例    return ctr.newInstance(h);}}


测试类

public class Client {public static void main(String[] args) throws Exception {Car car=new Car();InvocationHandler h=new TimeHandler(car);Moveable m=(Moveable) Proxy.newProxyInstance(Moveable.class,h);m.move();}}

结果如图




原创粉丝点击