简介
代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。
为了保持行为的一致性,代理类和委托类通常会实现相同的接口,所以在访问者看来两者没有丝毫的区别。通过代理类这中间一层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托类对象,同时也为实施不同控制策略预留了空间,从而在设计上获得了更大的灵活性。Java 动态代理机制以巧妙的方式近乎完美地实践了代理模式的设计理念。
jdk动态代理
java.lang.reflect.InvocationHandler
接口中定义了一个invoke方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
第一个参数proxy一般是指代理类,method是被代理的方法,args为该方法的参数数组。这个抽象方法在代理类中动态实现。
java.lang.reflect.Proxy
代理类,通过以下方法生成一个代理类
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException {...}
它返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)
所谓DynamicProxy是这样一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些 interface。你当然可以把该class的实例当作这些interface中的任何一个来用。当然,这个DynamicProxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。
在使用动态代理类时,我们必须实现InvocationHandler接口。
动态代理步骤
- 创建一个实现接口InvocationHandler的类,它必须实现invoke方法
- 创建被代理的类以及接口,被代理类实现该接口
- 通过Proxy的静态方法
newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
创建一个代理类。 - 通过代理调用方法
示例
- 创建接口
public interface Subject {
public String doSomething(String input);
}
- 创建被代理类并实现接口
public class SubjectImpl implements Subject {
@Override
public String doSomething(String input) {
System.out.println("我是被代理类...");
return input;
}
}
- 创建InvocationHandler接口的实现类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class InvocationHandlerImpl implements InvocationHandler {
/**
* 被代理类对象
*/
private Object subject;
public InvocationHandlerImpl(Object subject) {
this.subject = subject;
}
/**
* @param proxy 代理类
* @param method 被代理类的方法
* @param args 被代理类方法的参数
* @return 返回方法调用的结果
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("我是代理类对象通过InvocationHandler打印...before");
// 通过反射调用被代理类的方法
Object result = method.invoke(subject, args);
System.out.println("我是代理类对象通过InvocationHandler打印...after");
return result;
}
}
- 创建一个测试的主类主方法
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class TestMain {
public static void main(String[] args) {
// 被代理类对象
Subject subject = new SubjectImpl();
// 创建一个InvocationHandler
InvocationHandler handler = new InvocationHandlerImpl(subject);
// 获得被代理类的类加载器
ClassLoader loader = subject.getClass().getClassLoader();
// 获得被代理类实现的接口
Class[] interfaces = subject.getClass().getInterfaces();
// 创建代理类
Subject proxySubject = (Subject) Proxy.newProxyInstance(loader, interfaces, handler);
// 打印代理类名字
System.out.println("代理类的名字:" + proxySubject.getClass().getName());
// 执行方法
System.out.println(proxySubject.doSomething("我是输入的变量,将会被打印"));
}
}
- 运行结果