署理设计模式
代理设计模式

Proxy代理设计模式是一种控制对象访问的设计模式,类似于网络代理,网络代理机制如下图:
Proxy代理设计模式机制如下:
代理模式UML图如下:
代理模式顺序图如下:
客户端程序通过代理程序来访问真正的目标程序,代理程序对外隐藏了目标程序。普通代理设计模式例子代码如下:
interface ProxyBase{ public void f(); public void g(); public void h(); } //代理程序 class Proxy implement ProxyBase{ private ProxyBase implementation; public Proxy(){ //目标程序 implementation = new ProxyImplementation(); } public void f(){ implementation.f(); } public void g(){ implementation.g(); } public void h(){ implementation.h(); } } //目标程序 class ProxyImplementation implements ProxyBase{ public void f(){ System.out.println(“ProxyImplementation.f()”); } public void g(){ System.out.println(“ProxyImplementation.g()”); } public void h(){ System.out.println(“ProxyImplementation.h()”); } } //客户端程序调用代理 public class ProxyDemo{ public static void main(String[] args){ //客户端调用代理程序 Proxy p = new Proxy(); p.f(); p.g(); p.h(); } }从JDK1.3以后,java引入动态代理机制,java的动态代理只能针对接口进行动态代理,即要实现动态代理的类必须实现接口,CGLIB提供了针对类的动态代理功能。JDK动态代理的例子如下:
demo1:
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * 代理接口 * @author jacky * */ interface Foo{ public void f(String s); public void g(int i); public void h(int i, String s); } /** * 接口实现类,即被代理类 * @author jacky * */ class FooImpl implements Foo{ public void f(String s){ System.out.println("打印FooImpl.f(), s="+s); } public void g(int i) { System.out.println("FooImpl.g(), i="+ i); } public void h(int i, String s) { System.out.println("FooImpl.h(), i=" + i + ", s=" + s); } } /** * 动态代理处理类 * @author jacky * */ class ProxyHandler implements InvocationHandler{ //代理实现类 private Object delegate; public ProxyHandler (Object obj) { delegate = obj; } public Object invoke(Object proxy, Method method, Object[] args){ System.out.println("Before mothod:" + method); try { method.invoke(this.delegate, args); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("After mothod:" + method); return null; } } public class DynamicProxyDemo{ public static void main(String[] args){ //初始化动态代理处理类 Foo foo = new FooImpl(); ProxyHandler handler = new ProxyHandler(foo); //产生动态代理 Foo proxy = (Foo)Proxy.newProxyInstance(Foo.class.getClassLoader(), new Class[]{Foo.class}, handler); proxy.f("f"); proxy.g(1); proxy.h(2, "h"); } }
demo2:
import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.*; /** * 接口 * @author jacky * */ interface Person { String getName(); String getGender(); void setName(String name); void setGender(String gender); void setRate(int rate); int getRate(); } /** * 接口实现类,被代理类 * @author jacky * */ class PersonImpl implements Person { String name; String gender; String interests; int rate; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public String getInterests() { return interests; } public void setInterests(String interests) { this.interests = interests; } public int getRate() { return rate; } public void setRate(int rate) { this.rate = rate; } } /** * 动态代理处理类 * @author jacky * */ class OwnerInvocationHandler implements InvocationHandler{ private Person personBean; public OwnerInvocationHandler(Person personBean){ this.personBean = personBean; } public Object invoke(Object proxy, Method method, Object[] args) throws IllegalAccessException { try { if(method.getName().startsWith("get")){//如果方法名为get,就调用person类内的get相应方法 return method.invoke(personBean, args); }else if(method.getName().equals("setRate")){ // 如果方法是setRate,则抛出异常 throw new IllegalAccessException("access deny"); }else if(method.getName().startsWith("set")){ //如果为set,就调用person类内的set相应方法 return method.invoke(personBean, args); }else { System.out.println("non method invoke"); } } catch (InvocationTargetException e) { e.printStackTrace(); } return null; } } /** * 动态代理处理类 * @author jacky * */ class NonInvocationHandler implements InvocationHandler{ // private Person person; public NonInvocationHandler(Person person){ this.person = person; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if(method.getName().startsWith("setRate")){ return method.invoke(person, args); }else if (method.getName().startsWith("get")){ return method.invoke(person, args); } else { System.out.println("non method invoke"); return null; } } } /** * 主类 * @author jacky * */ public class MyDynamicProxy { public Person getOwnerPersonBeanProxy(Person person){ return (Person)Proxy.newProxyInstance(person.getClass().getClassLoader(), person.getClass().getInterfaces(), new OwnerInvocationHandler(person)); } public Person getNonPersonBeanProxy(Person person){ return (Person)Proxy.newProxyInstance(person.getClass().getClassLoader(), person.getClass().getInterfaces(), new NonInvocationHandler(person)); } public static void main(String[] args) { MyDynamicProxy mdp = new MyDynamicProxy(); mdp.test(); } public void test(){ Person person = getPersonBeanFromDB1(); Person personProxy = getOwnerPersonBeanProxy(person); System.out.println(personProxy.getName()); try { personProxy.setRate(2); } catch (Exception e) { System.out.println("can not setRate"); } Person person1 = getPersonBeanFromDB1(); Person personProxy2 = getNonPersonBeanProxy(person1); System.out.println(personProxy2.getName()); personProxy2.setRate(2); System.out.println(personProxy2.getRate()); } /** * 返回接口实现类 * @return */ private Person getPersonBeanFromDB1(){ Person pb = new PersonImpl(); pb.setName("remy"); pb.setGender("girl"); pb.setRate(1); return pb; } }
动态代理和普通的代理模式的区别:动态代理中的代理类是由java.lang.reflect.Proxy类在运行期时根据接口定义,采用Java反射功能动态生成的。和java.lang.reflect.InvocationHandler结合,可以加强现有类的方法实现。动态带来自定义Handler实现InvocationHandler接口,自定义Handler实例化时,将代理的实现类传入自定义Handler对象中。自定义Handler需要实现invoke方法,该方法可以使用Java反射调用实现类的实现的方法,同时当然可以实现其他功能,例如在调用实现类方法前后加入Log,实现安全认证等。而Proxy类根据Handler和需要代理的接口动态生成一个接口实现类的对象。当用户调用这个动态生成的实现类时,实际上是调用了自定义Handler的invoke方法。
JDK中代理模式的应用:
JDK动态代理.
RMI.
参考:http://developer.51cto.com/art/201104/253625.htm
版权声明:本文为博主原创文章,未经博主允许不得转载。