设计模式之-代理模式(Proxy)

代理(Proxy)模式标准定义:为其余对象提供一种代理以控制对这个对象的访问。java

代理就是一我的或一个机构表明另外一我的或者一个机构采起行动。某些状况下,客户不想或者不可以直接引用一个对象,代理对象能够在客户和目标对象直接起到中介的做用。客户端分辨不出代理主题对象与真实主题对象。代理模式能够并不知道真正的被代理对象,而仅仅持有一个被代理对象的接口,这时候代理对象不可以建立被代理对象,被代理对象必须有系统的其余角色代为建立并传入。ide

代理模式实现的方式具体有2种。一、经过继承实现;二、经过聚合的方式实现。this

 

/**url

* @describe: 定义接口.net

*/代理

public interface Animal {对象

    public void move();blog

}继承

 

/**接口

* @describe: 接口实现类

*/

package test.com.java.proxy.example;

public class Persion implements Animal{

 

@Override

public void move() {

    System.out.println("不断的移动中...");

    try {

        Thread.sleep(1000);

    } catch (InterruptedException e) {

        e.printStackTrace();

    }

    System.out.println("移动结束...");

    }

}

 

/**

*

* @describe:一、采用继承的方式对Persion进行代理,增长打印方法执行时间的新功能

*/

package test.com.java.proxy.example;

public class PersionExtendsProxy extends Persion{

 

@Override

public void move() {

    long start=System.currentTimeMillis();

    System.out.println("move() start...");

    super.move();

    long end=System.currentTimeMillis();

    System.out.println("move() end... times:"+(end-start));

    }

}

 

/**

*

* @describe:二、采用聚合的方式对Proxy类进行代理(面向接口的方式代理)

*/

package test.com.java.proxy.example;

public class PersionProxy implements Animal{

 

    private Animal a;

    public PersionProxy(Animal a){

    this.a=a;

}

@Override

public void move() {

    long start=System.currentTimeMillis();

    System.out.println("move() start...");

    a.move();

    long end=System.currentTimeMillis();

    System.out.println("move() end... times:"+(end-start));

    }

}

 

package test.com.java.proxy.example;

public class Test {

    public static void main(String[] args) {

    //采用继承的方式实现代理

    Animal proxy=new PersionExtendsProxy();

    proxy.move();

    System.out.println("----------------------------------");

    //采用聚合的方式实现代理

    Persion p=new Persion();

    Animal proxy1=new PersionProxy(p);

    proxy1.move();

    }

}

 

运行结果:

move() start...

不断的移动中...

移动结束...

move() end... times:1000

----------------------------------

move() start...

不断的移动中...

移动结束...

move() end... times:1001

 

2种实现方式比较:

1)因为java仅支持单继承,因此采用继承的方式实现不够灵活,若是还须要继承其余的类的话,那就费了;

2)若是须要继续增长新的代理功能,那么采用继承的方式的话,就须要不断的继承下去,这样类的层次结构会愈来愈深,维护起来很不方便。

综上所述:采用聚合的方式实现代理比较好。下面咱们讨论下JDK动态代理实现。

JDK动态代理实现以下:

Animal.java、Persion.java文件同上

下面须要咱们自定义一个实现InvocationHandler接口的处理方法类,在要代理的对象方法先后增长适当的逻辑。

 

package test.com.java.proxy.dynamic;

 

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

 

public class MyInvocationHandler implements InvocationHandler{

 

private Object target;

MyInvocationHandler() {

    super();

}

MyInvocationHandler(Object target) {

    super();

    this.target = target;

}

@Override

public Object invoke(Object o, Method method,Object[] args) throws Throwable {

    System.out.println("o:"+o.getClass().getName());

    System.out.println("method:"+method);

    System.out.println("args:"+args);

    long start=System.currentTimeMillis();

    System.out.println("move() start...");

    Object result=method.invoke(target, args);

    long end=System.currentTimeMillis();

    System.out.println("move() end... times:"+(end-start));

    System.out.println("result:"+result);

    return result;

}

 

}

 

/**

*

* @describe:使用JDK动态代理的方式

* @author wenqi 2017年11月26日

*

*/

package test.com.java.proxy.dynamic;

 

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Proxy;

 

public class Test {

public static void main(String[] args) {

    Animal a=new Persion();

    InvocationHandler handler=new MyInvocationHandler(a);

    Animal proxy=(Animal) Proxy.newProxyInstance(a.getClass().getClassLoader(), a.getClass().getInterfaces(), handler);

    proxy.move();

    }

}

 

运行结果以下:

o:com.sun.proxy.$Proxy0

method:public abstract void test.com.java.proxy.dynamic.Animal.move()

args:null

move() start...

不断的移动中...

move() end... times:1002

result:null

 

生成动态代理Class文件相似以下:

 

public class Proxy {

public static Object newProxyInstance(Class infce, InvocationHandler h) throws Exception {

    String methodStr = "";

    String rt = "\r\n";

    Method[] methods = infce.getMethods();

    for(Method m : methods) {

    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 +

    "}";

    }

 String src =

"package com.bjsxt.proxy;" + rt +

"import java.lang.reflect.Method;" + rt +

"public class $Proxy1 implements " + infce.getName() + "{" + rt +

" public $Proxy1(InvocationHandler h) {" + rt +

" this.h = h;" + rt +

" }" + rt +

" InvocationHandler h;" + rt +

methodStr +

"}";

String fileName =

"d:/src/$Proxy1.java";

File f = new File(fileName);

FileWriter fw = new FileWriter(f);

fw.write(src);

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:/" + "d:/src/")};

URLClassLoader ul = new URLClassLoader(urls);

Class c = ul.loadClass("$Proxy1");

System.out.println(c);

Constructor ctr = c.getConstructor(InvocationHandler.class);

Object m = ctr.newInstance(h);

 

return m;

}

}

 

Spring中aop是动态代理具体应用,相关文章以下:

http://blog.csdn.net/guoquanyou/article/details/6754916

相关文章
相关标签/搜索