共计 2793 个字符,预计需要花费 7 分钟才能阅读完成。
动态代理
即,动态代理是利用 java 反射技术,在运行时创建一个实现某些给定接口的新类。
栗子
先定义接口
public interface people {
public String work();
}
实现该接口
public class Teacher implements people{
@Override
public String work() {
System.out.println(“ 教书育人 ”);
return “ 教书 ”;
}
}
编写代理类
import com.sun.xml.internal.ws.api.pipe.FiberContextSwitchInterceptor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class WorkHandler implements InvocationHandler {
// 代理类的对象
private Object obj;
public WorkHandler(){
}
// 在调用这个方法的时候,会被调度到 invoke 方法,并将参数传入
public WorkHandler(Object obj){
this.obj = obj;
}
// 在调用给类的方法的时候,会被调度到 invoke 方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 真实对象执行之前添加操作
// 调用 obj 类的 method 方法,并且参数为 args
Object invoke = method.invoke(obj, args);
// 真实对象执行后添加操作
return invoke;// 返回执行的结果
}
}
最后运行
import java.io.FileInputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Main {
public static void main(String[] args){
// 要代理的对象
people people = new Teacher(); // 创建要代理的真实对象
// 进行注册
InvocationHandler handler = new WorkHandler(people);
// 进行创建代理对象
// 定义一个代理对象
people proxy;
// 调用 Proxy.newProxyInstance 方法
// 需要传入真实对象实现的接口,为下一步调用该方法做准备
// 将 handler 关联到 invocationHandler 对象,用于调度到 invoke 方法
// 由于返回的对象为 object 类型,需要进行强制类型转换,保留 people 接口定义的方法
// 最后一个参数要对对象进行关联,最后批量生产出对象
proxy = (people) Proxy.newProxyInstance(handler.getClass().getClassLoader(), people.getClass().getInterfaces(), handler);
System.out.println(proxy.work());
}
}
第一个参数
第一个参数是运行时,创建的代理对象。
反射 +IO 操作读取 class 文件
import java.io.FileInputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Main {
// 需要使用 static 让其加载进入内存
static class myClassLoader extends ClassLoader{
private String classPath; // 获取当前类的在磁盘中保存的地址
// 通过构造函数将地址注入
public myClassLoader(String classPath){
this.classPath = classPath;
}
// 将文件内容加载进入内存
private byte[] loadByte(String name) throws Exception{
// 获取一个输入流,
FileInputStream fis = new FileInputStream(classPath + “/” + name + “.class”);
// 获取长度
int len = fis.available();
// 定义 byte 数组
byte[] data = new byte[len];
// 加载进入内存
fis.read(data);
// 关闭流
fis.close();
return data;
}
// 重写 findClass 方法,让加载的时候调用 findClass 方法
protected Class<?> findClass(String name) throws ClassNotFoundException{
try{
// 读取文件到数组中
byte[] data = loadByte(name);
// 将字节码加载进入内存当中
return defineClass(name, data, 0, data.length);
}catch(Exception e){
e.printStackTrace();
}
return null;
}
}
public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, ClassNotFoundException {
// 先初始化该类
myClassLoader classLoader = new myClassLoader(“/home/ming”);
// 此时会调用 findClass 加载 Test.class 加载进入内存当中
Class clazz = classLoader.loadClass(“com.ming.Test”);
// 实例化该类对象
Object obj = clazz.newInstance();
// 获取 clazz 该类方法中名称为 hello,参数为空的方法。
Method helloMethod = clazz.getDeclaredMethod(“helloWorld”, null);
// 调用该方法
// 调用 obj 类中的 helloMethod,参数为空的方法。
helloMethod.invoke(obj, null);
}
}