代理模式:通过代理间接的调用被代理对象的方法,结构如下:
image.png
Java的反射包提供了一个Porxy类和InvokationHandler接口。它们结合在一起后可以创建动态代理类。Porxy类基于传递的参数创建动态代理类。InvokationHandler则用于激发动态代理类的方法。这个过程是在程序执行过程中动态生成与处理的,所以叫动态代理。分析一下
Porxy类
Porxy类提供了一个静态方法创建动态代理类。
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
1、ClassLoader:ClassLoader会定义动态代理类,ClassLoader可以通过类或者接口获得,如果我们想通过接口获得,调用方法如下。
Task.class.getClassLoader()
如果通过类来获得,加入我们有一个类TaskImpl实现了Task接口,我们有个TaskImpl的对象ob,然后ClassLoader获取方法如下
ob.getClassLoader()
2、 Class<?>[] interfaces:动态代理类需要实现的接口
3、InvocationHandler:传递一个实现了InvokationHandler接口的类的实例
InvokationHandler
InvokationHandler是Java 反射包里面的一个接口。InvokationHandler通过用户类来实现,来激发一个动态代理类的方法。它只有一个方法:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
1、Object:实现方法的代理对象
2、Method:代理实例激发的方法,Porxy参数中的接口方法
3、Object[]:传递给方法的一系列参数
实现
1、我们提供一个接口
package me.aihe;
public interface Task {
void setData(String data);
int getCalData(int x);
}
2、实现这个接口
package me.aihe;
public class TaskImpl implements Task {
@Override
public void setData(String data) {
System.out.println(data+ " Data is saved");
}
@Override
public int getCalData(int x) {
return x * 10;
}
}
3、定义自己的InvokationHandler类,并且实现InvokationHandler接口的Invoke方法
package me.aihe;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class MyInvokationHandler implements InvocationHandler {
private Object obj;
public MyInvokationHandler(Object object){
this.obj = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result;
if(method.getName().contains("get")){
System.out.println("...get Method Executing...");
}else{
System.out.println("...set Method Executing...");
}
result = method.invoke(obj, args);
return result;
}
}
4、创建一个工厂类获取动态代理类:
package me.aihe;
import java.lang.reflect.Proxy;
public class ProxyFactory {
public static Object newInstance(Object ob) {
return Proxy.newProxyInstance(ob.getClass().getClassLoader(),
new Class<?>[] { Task.class }, new MyInvokationHandler(ob));
}
}
5、提供我们的测试类
package me.aihe;
public class Test {
public static void main(String[] args) {
Task task = (Task)ProxyFactory.newInstance(new TaskImpl());
task.setData("Test");
System.out.println("============");
System.out.println(task.getCalData(5));
}
}
看到程序的输出结果:
...set Method Executing...
Test Data is saved
============
...get Method Executing...
50
总结
动态代理的实现流程:
1、创建一个接口
2、提供一个实现这个接口的类
3、创建一个实现了InvokationHandler接口的类,实现Invoke方法。
传递参数:实现接口的类
4、可选:创建一个代理工厂。
返回值传递参数:ClassLoader,实现的接口,实现接口的类
参考: