前言

在Dubbo中,通过@Reference注解,让定义的接口引用去指向一个具体的接口实现,但是这个实现肯定不会是生产者端的实现,不然的话,RPC就没有意义了,所以我们现在来探究一下Dubbo中是如何实现的.

原理

dubbo的reference注解注入的源码 dubbo @reference注解的作用_RPC

总的来说,就是我们看似在调用生产者的方法实现,实际上调用的是本地生成的方法,这个生成方法多种多样,不过这个实现是在内存中的实现,也就是说,消费者并不能显式的看到它.

在这个接口实现中具体要做的事情很明确,就是向生产者发送数据进行通信,并且获取它的返回值.当方法的入参中有类对象时,需要进行序列化转为字节流进行传输.而在生产者,接收到字节流之后要进行反序列化,然后进行具体的实现,再将处理结果返回给消费者(有需要的话需要再次序列化和反序列化).

总结

@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("你在说什么");
    }
}

运行结果:

dubbo的reference注解注入的源码 dubbo @reference注解的作用_System_02