Proxy代理设计模式是一种控制对象访问的设计模式,类似于网络代理,网络代理机制如下图:
Proxy代理设计模式机制如下:
代理模式UML图如下:
代理模式顺序图如下:
![](https://img-my.csdn.net/uploads/201211/18/1353226969_8913.png)
客户端程序通过代理程序来访问真正的目标程序,代理程序对外隐藏了目标程序。普通代理设计模式例子代码如下:
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