您的位置:首页 > 编程语言 > Java开发

java代理模式

2015-10-31 23:22 387 查看
代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。代理模式一般涉及到的角色有抽象角色:声明真实对象和代理对象的共同接口代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装真实角色:代理角色所代表的真实对象,是我们最终要引用的对象首先来看普通的代理:
package com.lql.proxy;

//接口,代理对象和被代理对象都继承这个接口
public abstract class Subject {

public abstract void method();

}
package com.lql.proxy;

//被代理对象
public class RealObject extends Subject {

@Override
public void method() {
// TODO Auto-generated method stub
System.out.println("this is realObject's method");
}

}
package com.lql.proxy;

//代理对象类
public class ProxyObect extends Subject{

/**
* 在代理对象中有一个被代理对象的引用
* 这样就可以在代理类中操作被代理对象中的方法
* 从而实现对被代理对象的代理
*/
private RealObject realObject;

@Override
public void method() {
// TODO Auto-generated method stub
if(realObject == null){
realObject = new RealObject();
}
prePare();
realObject.method();
post();
}

private void post() {
// TODO Auto-generated method stub

}

private void prePare() {
// TODO Auto-generated method stub

}

}
package com.lql.proxy;

public class Test {

public static void main(String[] args) {

//父类的引用指向子类的对象
Subject subject = new ProxyObect();
//调用父类的对象,其实是调用子类对象的方法
subject.method();

}
}
以上是普通代理模式(静态代理模式),由上述代码可知,静态代理很不灵活。有一个被代理对象,都需要写一个代理对象。这样就使代码不够灵活。java中提供了动态代理来实现更为灵活的代理模式。java动态代理主要需要两个类:(1)Interface InvocationHandler:该接口中仅定义了一个方法public object invoke(Object obj,Method method, Object[]args)在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,args为该方法的参数数组。这个抽象方法在代理类中动态实现。(2)Proxy:该类即为动态代理类,作用类似于上例中的ProxyOubject,其中主要包含以下内容protected Proxy(InvocationHandlerh):构造函数,用于给内部的h赋值。static Class getProxyClass(ClassLoader loader, Class[]interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。static Object newProxyInstance(ClassLoaderloader, Class[] interfaces,InvocationHandlerh):返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)所谓DynamicProxy是这样一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些interface。你当然可以把该class的实例当作这些interface中的任何一个来用。当然,这个DynamicProxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作
package com.lql.dynamic.proxy2;

public interface Subject {

public int add(int a , int b);
public void myPrint();
}
package com.lql.dynamic.proxy2;

public class RealSubjext implements Subject {

@Override
public int add(int a, int b) {
// TODO Auto-generated method stub
return a + b;
}

@Override
public void myPrint() {
// TODO Auto-generated method stub
System.out.println("hello world");
}

}
package com.lql.dynamic.proxy2;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
* 动态代理真正的处理类,这个类必须实现InvocationHandler
* 实现InvocationHandler接口后,动态代理类就会将执行被代理对象方法的任务交给这个类来处理
* 这个类会自动调用invoke方法,这个方法会通过反射调用被代理类中的方法,实现代理
*
* @author Administrator
*
*/
public class DynamicSubject implements InvocationHandler {

//被代理对象要实现的接口的引用,通过这个引用可以指向被代理对象
private Object obj;

public DynamicSubject(){

}

public DynamicSubject(Object obj){
this.obj = obj;
}

/**
* 在这个方法这里打断点,可以看到,执行完客户端的subject.myprint()方法后
* 又执行这个方法,也就是代理对象又把执行被代理对象的方法的任务,交由这个方法执行
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub

preProxy();

method.invoke(obj, args);

postProxy();

return null;
}

private void postProxy() {
// TODO Auto-generated method stub
System.out.println("You also can do something after proxy");
}

private void preProxy() {
// TODO Auto-generated method stub
System.out.println("You can do something before proxy");
}

}
package com.lql.dynamic.proxy2;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class Client {

public static void main(String[] args) {

/**
* 定义一个被代理对象
*/
RealSubjext realSubjext = new RealSubjext();

/**
* 实际处理被代理对象方法的对象
*/
InvocationHandler invocationHandler = new DynamicSubject(realSubjext);

/**
* 获取被代理对象的类,需要用它来获取代理生成动态的生成一个代理对象
*/
Class<?> class1 = realSubjext.getClass();

//生成代理对象,代理对象并不负责执行被代理的方法,而是交由invocationHandler所指向类的invoke方法
//不过还需要代理对象指定一下执行被代理对象的哪个方法
Subject subject = (Subject) Proxy.newProxyInstance(class1
.getClassLoader(), class1.getInterfaces(), invocationHandler);

//代理对象告诉负责执行被代理对象方法dynamicSubject,你去回调被代理对象的myPrint()方法
//
subject.myPrint();

}
}
从上面的代码上可以看到,程序中并没有像静态代理那样写一个代理对象的ProxyObject类,而是通过java提供的Proxy.newProxyInstance()方法生成一个代理对象,然后完成代理的任务。(虽然事实上真正的活不是它来做的,给我的感觉是脏活累活都交给了InvocationHandler的实现类来做了)
以上的内容我是参考风中叶老师的视频,做的笔记。
                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: