在之前的设计模式博文《设计模式_代理模式(Java)》中,介绍了代理模式。它是为了提供额外的操作,而创建的用来替代实际对象的对象,原理和实现都较为简单,在这篇文章中我们主要是介绍Java中提供的动态代理。
动态代理比代理的思想更向前迈进一步,因为它可以动态地创建代理,并动态地处理对所代理方法的调用。在动态代理上所做的所有调用都会被重定向到单一的调用处理器(InvocationHandler
实现)上。在Java中,动态代理是通过反射机制进行实现的。
下面我们来逐步分析一下Java动态代理的具体实现:
/**目标接口**/
interface Driver{
/**目标方法**/
public void run();
public void stop(String c);
}
/**目标对象**/
class RealDriver implements Driver{
public void run() {
System.out.println("car is running");
}
public void stop(String c) {
if(c.equals("girls")){
System.out.println("car is stopping");
}
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 动态代理处理器
* 在动态代理上所做的所有调用都会被重定向到该处理器
**/
public class DynamicProxyHandler implements InvocationHandler{
public Object target;
public DynamicProxyHandler(Object o){
this.target=o;
}
/**
* 执行目标对象的方法
* proxy: 代理对象被传递进来
* method: 被调用方法
* args: 方法参数
***/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//转调之前处理
System.out.println("dididi~~~");
//转调具体目标对象的方法
Object o=method.invoke(target, args);
//转调之后处理
if(args!=null){
for(Object arg:args){
System.out.println(arg +" follow me, let's go!");
}
}
return o;
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
/**测试类**/
public class Test {
public static void main(String[] args) {
//目标对象实例化
Driver driver=new RealDriver();
//创建处理器对象
InvocationHandler invocationHandler=new DynamicProxyHandler(driver);
/**
* 获取目标对象的代理对象
* !重点语句
* driver.getClass().getClassLoader() 获取目标对象的类加载器
* driver.getClass().getInterfaces() 获取目标对象的接口,或者是接口的列表,
* 但不可以是类和抽象类,原因是动态生成的代理对象已经继承了Proxy类,无法继承其他类或者抽象类(Java单继承)
* invocationHandler 处理器对象
**/
Driver driverProxy=(Driver)Proxy.newProxyInstance(driver.getClass().getClassLoader(), driver.getClass().getInterfaces(), invocationHandler);
//调用代理对象方法
driverProxy.run();
driverProxy.stop("girls");
driverProxy.stop("ladys");
}
}
执行结果如下:
dididi~~~
car is running
dididi~~~
car is stopping
girls follow me, let's go!
dididi~~~
ladys follow me, let's go!
Spring的AOP实现其实也是通过这种方法进行的。
大家应该都注意到了再上述实现中的一些重点部分。一个是DynamicProxyHandler
类invoke()
方法中的Object o=method.invoke(target, args);
它将请求转发给被代理的对象target
。另一个是main()
方法中的Driver driverProxy=(Driver)Proxy.newProxyInstance(driver.getClass().getClassLoader(), driver.getClass().getInterfaces(), invocationHandler);
具体参数的意义我们已经在代码注释中给出,我们重点分析Proxy.newProxyInstance()
中发生的事情,在Proxy.newProxyInstance()
中主要执行了以下三步:
//获取代理对象引用
1. Class cl = getProxyClass(loader, interfaces);
//通过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型
2. Constructor cons = cl.getConstructor(new Class[]{InvocationHandler.class});
//返回代理对象,h为invocationHandler
3. return (Object) cons.newInstance(new Object[] { h });
生成的“driverProxy”继承了Proxy类并实现了Driver目标接口,代理调用的方法实际调用处理器的invoke()方法,而invoke()方法利用反射调用的是被代理对象的的方法。
感觉比较神奇,是吧。但是Java中实现的动态代理仍存在问题,例如必须要求目标对象拥有其目标接口,否则无法实现代理,那么很多场景下可能无法实现动态代理。cglib动态代理则解除了这种限制,并且有着较高的执行效率,我们在这里就不对cglib动态代理进行介绍了,想了解的同学可以移步《Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)》进行学习。
参考: