Dynamic Proxy Pattern 动态代理模式 代码 UML2009-09-07 15:07 代理的定义:为另一个对象提供一个替身或占位符以控制对这个对象的访问。
代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
代理模式一般涉及到的角色有:
抽象角色:声明真实对象和代理对象的共同接口;
代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。
动态代理类
Java动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类:
(1). Interface InvocationHandler:该接口中仅定义了一个方法Object:invoke(Object obj,Method method, Object[] args)。在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,如上例中的request(),args为该方法的参数数组。 这个抽象方法在代理类中动态实现。
(2).Proxy:该类即为动态代理类,作用类似于上例中的ProxySubject,其中主要包含以下内容:
Protected Proxy(InvocationHandler h):构造函数,估计用于给内部的h赋值。
Static Class getProxyClass (ClassLoader loader, Class[] interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。
Static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)。
所 谓Dynamic Proxy是这样一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些 interface。你当然可以把该class的实例当作这些interface中的任何一个来用。当然啦,这个Dynamic Proxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。
--------------------------------
代码:
package com.test.pattern.dynamicProxy;
public interface PersonBean {
public String getName();
public String getGender();
public String getInterests();
public int getHotOrNotRating();
public void setName(String name);
public void setGender(String gender);
public void setInterests(String interests);
public void setHotOrNotRating(int rating);
}
-----------------
package com.test.pattern.dynamicProxy;
public class PersonBeanImpl implements PersonBean{
private String name;
private String gender;
private String interests;
private int rating;
private int ratingCount;
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 getHotOrNotRating() {
if(this.ratingCount == 0){
return 0;
}
return this.rating/this.ratingCount;
}
public void setHotOrNotRating(int rating) {
this.rating+=rating;
this.ratingCount++;
}
}
-----------------------------
package com.test.pattern.dynamicProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class OwnerInvocationHandler implements InvocationHandler {
private PersonBean person;
public OwnerInvocationHandler(PersonBean person) {
this.person = person;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
try {
if (method.getName().startsWith("get")) {
return method.invoke(person, args);
} else if (method.getName().equals("setHotOrNotRating")) {
throw new IllegalAccessException();
} else if (method.getName().startsWith("set")) {
return method.invoke(person, args);
}
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
}
----------------------------------
package com.test.pattern.dynamicProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class NonOwnerInvocationHandler implements InvocationHandler {
private PersonBean person;
public NonOwnerInvocationHandler(PersonBean person) {
this.person = person;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
try {
if (method.getName().startsWith("get")) {
return method.invoke(person, args);
} else if (method.getName().equals("setHotOrNotRating")) {
return method.invoke(person, args);
} else if (method.getName().startsWith("set")) {
throw new IllegalAccessException();
}
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
}
----------------------------------------
package com.test.pattern.dynamicProxy;
import java.lang.reflect.Proxy;
public class PersonProxy {
public PersonBean getOwnerProxy(PersonBean person) {
return (PersonBean) Proxy.newProxyInstance(person.getClass()
.getClassLoader(), person.getClass().getInterfaces(),
new OwnerInvocationHandler(person));
}
public PersonBean getNonOwnerProxy(PersonBean person) {
return (PersonBean) Proxy.newProxyInstance(person.getClass()
.getClassLoader(), person.getClass().getInterfaces(),
new NonOwnerInvocationHandler(person));
}
}
-------------------------------------------
package com.test.pattern.dynamicProxy;
public class TestRun {
public static void main(String[] args) {
// 创建PersonBean实例对象
PersonBean lucy = new PersonBeanImpl();
lucy.setName("Lucy");
lucy.setGender("femaile");
lucy.setInterests("read books...");
PersonBean tom = new PersonBeanImpl();
tom.setName("Tom");
tom.setGender("femaile");
tom.setInterests("Play basketball...");
// 创建代理器
PersonProxy proxy = new PersonProxy();
// 创建对象lucy的代理对象
PersonBean lucyOwnerProxy = proxy.getOwnerProxy(lucy);
System.out.println("lucy:" + lucy.getName() + lucy);
System.out.println("lucyOwnerProxy:" + lucyOwnerProxy.getClass());
System.out.println("lucy.equals(lucyOwnerProxy):"
+ lucy.equals(lucyOwnerProxy));
System.out
.println("lucy == lucyOwnerProxy:" + (lucy == lucyOwnerProxy));
try {
lucyOwnerProxy.setHotOrNotRating(2);
} catch (Exception e) {
System.out.println("owner can not set his rate.");
}
// 创建对象Tom的代理
PersonBean tomNonOwnerProxy = proxy.getNonOwnerProxy(tom);
System.out.println("tom:" + tom.getName() + tom);
System.out.println("tomNonOwnerProxy:" + tomNonOwnerProxy.getClass());
System.out.println("tom.equals(tomNonOwnerProxy):"
+ tom.equals(tomNonOwnerProxy));
System.out.println("tom == tomNonOwnerProxy:"
+ (tom == tomNonOwnerProxy));
try {
tomNonOwnerProxy.setGender("male");
} catch (Exception e) {
System.out.println(" non owner can not set others' info.");
}
}
}
-----------------------------
运行结果:
lucy:Lucycom.test.pattern.dynamicProxy.PersonBeanImpl@61de33
lucyOwnerProxy:class $Proxy0
lucy.equals(lucyOwnerProxy):false
lucy == lucyOwnerProxy:false
owner can not set his rate.
tom:Tomcom.test.pattern.dynamicProxy.PersonBeanImpl@ca0b6
tomNonOwnerProxy:class $Proxy0
tom.equals(tomNonOwnerProxy):false
tom == tomNonOwnerProxy:false
non owner can not set others' info.
--------------------
动态代理模式 UML 图: