RPC实战与核心原理之动态代理了
动态代理
回顾
用来解决两个应用之间的通信,而网络则是两台l两台机器之间的“桥梁”,只有搭好桥梁才能把请求数据从一端传输到另一端,其中关键就是“可靠的传输”
背景
RPC的目标就是通过屏蔽调用细节,实现远程调用如同本地调用一样简单
在使用RPC时,一般的做法是先找服务提供方要接口,通过Maven或者其他工具把接口依赖到项目中,通过依赖注入的方式把接口注入项目中,然后在代码里面直接调用的方法
核心技术:动态代理
- RPC会自动给接口生成一个代理类,在项目中注入接口的时候,运行过程中实际绑定的是这个接口生成的代理类,在接口方法被调用的时候,实际上是被生成代理类拦截到了,这样就可以在生成的代理类中加入远程调用逻辑
动态代理
实现原理
/**
- 要代理的接口
*/
public interface Hello {
String say();
}
/**
- 真实调用对象
*/
public class RealHello {
public String invoke(){
return "i'm proxy";
}
}
/**
- JDK代理类生成
*/
public class JDKProxy implements InvocationHandler {
private Object target;
JDKProxy(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] paramValues) {
return ((RealHello)target).invoke();
}
}
/**
- 测试例子
*/
public class TestProxy {
public static void main(String[] args){
// 构建代理器
JDKProxy proxy = new JDKProxy(new RealHello());
ClassLoader classLoader = ClassLoaderUtils.getCurrentClassLoader();
// 把生成的代理类保存到文件
System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
// 生成代理类
Hello test = (Hello) Proxy.newProxyInstance(classLoader, new Class[]{Hello.class}, proxy);
// 方法调用
System.out.println(test.say());
}
}
- 给Hello接口生成一个动态代理类,并调用接口say()方法,但真实返回的值是来自RealHello里面的invoke()方法返回值
实现方法
- 在java领域(而我对java不熟),除了JDK默认的nvocationHandler能完成代理,还有很多第三方框架,如javassist、BYTE Buddy这样的框架也行
动态代理是一种具体的技术框架,那就会涉及到选型的问题,可从以下考虑
- 因为代理类是在运行中生成的,那么代理框架生成代理类的速度、生成代理类的字节码大小等等,都会影响到其性能——生成的字节码越小,运行所占资源就越小。
- 还有就是我们生成的代理类,是用于接口方法请求拦截的,所以每次调用接口方法的时候,都会执行生成的代理类,这时生成的代理类的执行效率就需要很高效。
- 最后一个是从我们的使用角度出发的,我们肯定希望选择一个使用起来很方便的代理类框架,比如我们可以考虑:API 设计是否好理解、社区活跃度、还有就是依赖复杂度等等。