使用背景
有时候我的某些接口去完成一些特定的功能时,我们可以把功能抽离出来用代理的方式去实现,只需要定义接口不需要实现类,用代码的方式去生成所谓的实现方法(其实是没有实现法方的,只是变相调用指定的功能,而CGLIB不是这样的)feign的实现过程就是这样的。
代码实现
定义方法代理的接口,用于实现代理方法具体要实现的内容
/**
* @Description 定义方法代理的接口
* @Date 2023-04-13 9:24
* @Author zhangkaiqiang
**/
public interface MethodHandler {
Object invoke(Object[] argv) throws Throwable;
}
代理方法的实现类,实现该方法具体要干什么事,返回什么结果
/**
* @Description 代理方法的实现类
* @Date 2023-04-13 9:45
* @Author zhangkaiqiang
**/
public class ZkqMethodHandler implements MethodHandler{
private Method method;
public ZkqMethodHandler(Method method) {
this.method = method;
}
// 具体代理的内容可以在这里实现
@Override
public Object invoke(Object[] argv) throws Throwable {
System.err.println("代理方法实现类:"+ method.getName());
return method.getName();
}
}
实现JKD动态代理接口,根据JDK的动态方法名去动态调用对应的实现该方法的类的实例
/**
* @Description 实现JKD动态代理接口
* @Date 2023-04-13 9:05
* @Author zhangkaiqiang
**/
public class ZkqInvocationHandler implements InvocationHandler {
private final Map<Method, MethodHandler> dispatch;
public ZkqInvocationHandler(Map<Method, MethodHandler> dispatch) {
this.dispatch = dispatch;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 这个是JDK的接口代理
System.err.println("当前执行的方法名是:"+ method.getName());
// method这个method是接口的method, 我们要调用实现先类的method
return dispatch.get(method).invoke(args);
}
}
反射生产代理类,根据传进来的Class对象动态生成所有方法的实例对象
/**
* @Description 反射生产代理类
* @Date 2023-04-13 9:08
* @Author zhangkaiqiang
**/
public class ReflectiveZkq {
public static <T> T newInstance(Class<T> target) {
Method[] methods = target.getMethods();
Map<Method, MethodHandler> map = new HashMap<Method, MethodHandler>();
for (Method method: methods) {
// 反射生产代理方法这个是接口代理,JDK只支持接口代理,不支持类代理
map.put(method, new MethodHandler.ZkqMethodHandler(method));
}
ZkqInvocationHandler handler = new ZkqInvocationHandler(map);
T proxy = (T) Proxy.newProxyInstance(target.getClassLoader(), new Class<?>[]{target}, handler);
return proxy;
}
}
测试JDK接口动态代理
使用main
可以直接生成和调用我们写的代理对象
public class DemoApplication {
public static void main(String[] args) throws IOException {
ZkqInterface zkqInterface = ReflectiveZkq.newInstance(ZkqInterface.class);
System.err.println("代理方法返回的结果" + zkqInterface.zkqMethod());
}
}
测试结果
当前执行的方法名是:zkqMethod
代理方法实现类:zkqMethod
代理方法返回的结果zkqMethod