代理模式是Java设计模式中的一种,其特征为代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现业务,而是通过调用委托类对象的相关方法来提供具体业务。
在Java中的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过这个类和接口可以生成JDK动态代理或动态代理对象。
按照代理的创建时间不同,可以分为两种:
动态代理的实现原理有些类似于过滤器的实现原理,但有所不同。动态代理的代理类与委托类之间的关系更像是明星与经纪人之间的关系,也就是说,如果你想找某个明星演出的话,并不是找他本人,而是找到他的经纪人就可以了。动态代理的实现过程很类似于这个过程,具体请看下图:
Proxy类是Java的java.lang.reflect包下提供的,该类用于创建动态代理类和代理对象的静态方法,它也是所有动态代理类的父类。如果在程序中为一个或多个接口动态地生成实现类,就可以用Proxy类来创建动态代理类;如果需要为一个或多个接口动态地创建实例,也可以使用Proxy类来创建动态代理实例。
方法摘要 | |
---|---|
static InvocationHandler | getInvocationHandler(Object proxy) |
static Class<?> | getProxyClass(ClassLoader loader, Class<?>… interfaces) |
static boolean | isProxyClass(Class<?> cl) |
static Object | newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) |
InvocationHandler接口提供了invoke()方法,用于替换代理对象的每一个方法。真实业务类可以通过代理类对象调用InvocationHandler接口提供的invoke()方法,来替代调用委托类的真实方法。
以下是InvocationHandler的API内容:
方法摘要 | |
---|---|
Object | invoke(Object proxy, Method method, Object[] args) |
Object invoke(Object proxy, Method method, Object[] args):在代理实例上处理方法调用并返回结果。在与方法关联的代理实例上调用方法时,将在调用处理程序上调用此方法。
利用Java提供的Proxy类和InvocationHandler接口来生成动态代理类或动态代理对象,具体实现步骤如下:
public interface Person {
void sayMe();
void sayHello(String name);
}
public class MyInvocationHandler implements InvocationHandler {
/**
* 执行动态代理对象的所有方法时,都会被替换成执行下面的invoke()方法.
* * 参数proxy:代表动态代理对象.
* * 参数method:代表正在执行的方法.
* * 参数args:代表调用目标方法时传入的实参.
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("---正在执行的方法: "+method);
if(args == null){
System.out.println("当前调用的方法没有参数.");
}else{
System.out.println("当前调用的方法需要传入的实参为:");
for (Object val : args) {
System.out.println(val);
}
}
return null;
}
}
public class ProxyTest {
public static void main(String[] args) {
// 创建一个InvocationHandler对象
InvocationHandler handler = new MyInvocationHandler();
// 通过Proxy类使用指定的InvocationHandler来生成动态代理对象
Person p = (Person)Proxy.newProxyInstance(Person.class.getClassLoader(), new Class[]{Person.class}, handler);
// 调用动态代理对象的业务方法
p.sayMe();
p.sayHello("张无忌");
}
}
通过Java提供的Proxy类和InvocationHandler接口生成的动态代理类,可以阻止调用委托类的方法、过滤参数及修改对应方法的返回值等作用。实现业务接口方法的实现类即委托类,具体操作如下:
public class Fanbingbing implements Person {
@Override
public void sayMe() {
System.out.println("我真的是范冰冰哦!");
}
@Override
public String sayHello(String name) {
System.out.println("你好:"+name+",我等你很久了...");
return "我终于见到范冰冰啦!";
}
}
public class FanbingbingTest {
public static void main(String[] args) {
Person p = (Person) Proxy.newProxyInstance(
Person.class.getClassLoader(),
Fanbingbing.class.getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
// 通过method的getName()方法获取业务方法名,进行阻止.
if (method.getName().equals("sayMe")) {
System.out.println("你想多了,哪那么容易见到啊!");
return null;
}
// 通过args获取实参,进行修改
if(method.getName().equals("sayHello")){
String name = (String)args[0];
method.invoke(Class.forName("app.java.proxy.Fanbingbing").newInstance(), "某局长");
}
// 修改返回值
if(method.getName().equals("sayHello")){
return "都是假的!";
}
return null;
}
});
p.sayMe();
p.sayHello("张无忌");
}
}
转载说明:请注明作者及原文链接,谢谢!
原文地址:http://blog.csdn.net/longestory/article/details/46317077