前言
在Dubbo中,通过@Reference注解,让定义的接口引用去指向一个具体的接口实现,但是这个实现肯定不会是生产者端的实现,不然的话,RPC就没有意义了,所以我们现在来探究一下Dubbo中是如何实现的.
原理
总的来说,就是我们看似在调用生产者的方法实现,实际上调用的是本地生成的方法,这个生成方法多种多样,不过这个实现是在内存中的实现,也就是说,消费者并不能显式的看到它.
在这个接口实现中具体要做的事情很明确,就是向生产者发送数据进行通信,并且获取它的返回值.当方法的入参中有类对象时,需要进行序列化转为字节流进行传输.而在生产者,接收到字节流之后要进行反序列化,然后进行具体的实现,再将处理结果返回给消费者(有需要的话需要再次序列化和反序列化).
总结
@Reference注解就是用于标记这个服务具体使用了生产者的哪个接口实现,而为了标记这个接口实现方法就很多了,这里就不再介绍了.
代码解释
如果你更喜欢看代码,就把这些摘走吧(以下仅为解释消费者端):
接口:ShenService.java
/**
* 接口
* @date 2019/9/28 15:13
*/
public interface ShenService {
String test();
String getName(String ip);
}
调用服务方法时实际调用的类RealShenService.java:
/**
* 消费者端不存在的类,实际应用中是在JVM中使用
* CGLib生成的实现接口的类.生成在JVM中
* @date 2019/9/28 15:21
*/
public class RealShenService implements ShenService {
private String target ;
public void setTarget(String target) {
this.target = target;
}
@Override
public String test() {
System.out.println("啊,有人调用了test方法,现在要发送给生产者了");
//发送信息给生产者
Communicate.send(target);
return "";
}
@Override
public String getName(String content) {
System.out.println("啊,有人调用了getName方法,现在要发送给生产者了");
Communicate.send(target,content);
return "";
}
}
模拟通信的Communicate.java
/**
* 进行通信的核心方法
* @date 2019/9/28 15:22
*/
public class Communicate {
static void send(String target){
//定义一个socket通信,发送到生产者那里
System.out.println("发送信息到:" + target);
}
public static Object send(String target, String content) {
System.out.println("发送信息'" + content + "'到:" + target);
return new Object();
}
}
Service工厂ProxyFactory.java:
/**
* CGLib代理工厂(模拟)
* @date 2019/9/28 15:15
*/
public class ProxyFactory {
public static Object create(Class<?> target,String ip){
try {
RealShenService shenService = new RealShenService();
//CGLib生成一个实现了接口的类,创建了这个生成类的对象
shenService.setTarget(ip);
return shenService;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
测试Test.java:
/**
* @Date: 2019/9/18 21:45
*/
public class Test {
private static ShenService shenService;
static{
//@Reference,ip标记具体调用的是哪个serviceImpl,这里可以有多种实现,我这只是其中一种想法
shenService = (ShenService) ProxyFactory.create(ShenService.class,"tcp:shenshaoming/ShenServiceImpl");
}
public static void main(String[] args) {
shenService.test();
shenService.getName("你在说什么");
}
}
运行结果: