代理是一种常用的设计模式,其目的是为其他对象提供一个代理可以控制对某个对象的访问,代理类负责为委托类预处理消息、过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。代理分为静态代理和动态代理,静态代理是在编译期间进行代理操作,动态代理是在程序运行期间进行代理操作。本文简要介绍动态代理技术。
动态代理技术分为两类:Java JDK动态代理和CGLIB动态代理,前者是基于反射技术实现,后者基于继承机制实现。
Java JDK动态代理机制的出现,是的开发人员不用手工编写代理类,只要简单制定一组接口及委托对象,就能动态获得代理类,代理类会将所有的方法调用分派到委托对象上反射执行。
JDK动态代理的四个步骤,其中2~4步骤也即Proxy的静态方法Proxy.newInstance的执行过程:
// 1.通过InvocationHandler创建自己的调用处理器,类似于回调函数
InvocationHandler invocationHandler = new InvocationHandlerImpl();
// 2.为Proxy类指定ClassLoader和一组接口来创建动态代理类
Class clazz = Proxy.getProxyClass(classLoader, new Class[]{Interface.Class,...});
// 3.通过反射机制获得动态代理类的构造函数,参数是调用处理器类型
Constructor constructor = clazz.getConstructor(new Class[] {InvocationHandler.class,...});
// 4.通过构造函数创建动态代理类实例
Interface interface = (Interface) constructor.newInstance(new Object()[invocationHandler]);
一个JDK动态代理示例:
public class TestJDKProxy {
interface Hello {
void sayHello(String name);
}
static class IHello implements Hello {
@Override
public void sayHello(String name) {
System.out.println("hello " + name);
}
}
static class JDKProxy implements InvocationHandler {
private Object tartget;
public <T> T bindNew(T t) {
this.tartget = t;
return (T) Proxy.newProxyInstance(t.getClass().getClassLoader(), t.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before execute ...");
Object result = method.invoke(tartget, args);
System.out.println("after execute ...");
return result;
}
}
public static void main(String ... args) {
Hello hello = new JDKProxy().bindNew(new IHello());
hello.sayHello("Jerry");
}
}
JDK动态代理优点:
- JDK本身支持,最小化依赖关系,简化开发和维护
- 跟随JDK版本升级,而字节码类库通常需要进行更新以保证新版Java上能用
- 代码实现简单
JDK动态代理缺点:
- 被代理类必须有已实现的接口,因为JDK提供的Proxy类创建代理对象时需要