一、SPI
引入:spi标准:
1、需要在 classpath 下创建一个目录,该目录命名必须是:META-INF/service
2、在该目录下创建一个 properties 文件,该文件需要满足以下几个条件 :
2.1 文件名必须是扩展的接口的全路径名称
2.2 文件内部描述的是该扩展接口的所有实现类
2.3 文件的编码格式是 UTF-8
3、通过 java.util.ServiceLoader 的加载机制来发现
SpringfactoryLoader---spring加载器
ExtentionLoader--dubbo加载器;
dubbo的过程:
文件路径为@SPI注解标记的全路径名:com.test.dubbo
内容为接口的实现类(key-value):mydubbo=com.test.dubbo.mydubbo
服务启动时,会加载约定的配置classpath下的全类路径的文件,并通过ExtentionLoader会将所有的实现类以key-value的形式放进一个map,当扫面到@Spi(“mydubbo”)(---接口必须要有这个注解和具体的value),会从缓存的map内,取出我们需要的实现类,【默认是@Spi(“dubbo”)具体执行ExtensionLoader.getExtensionLoader.getExtension】
多个实现类 ,可以通过URL或者@Adaptive 来具体调用:
1、@Adaptive主要用于在spi多个实现类中找一个数据合适的扩展实现,只能一个实现类用该注解;
2、方法层面:放在SPI接口的方法上@Adaptive注解中的value属性,才会被处理生效,也就是也给value属性 赋一个文件对应的key值 比如mydubbo;
其他:rpc远程过程调用,负载均衡,重试机制,客户端缓存,zookeeper注册中心;
二、服务暴露\引用
引入:Springboot启动监听器的 ,待Spring容器refresh之后,开始执行callrunner,运行器触发dubbo的服务开始注册,暴露,发现等
暴露和注册:第一步将持有的服务实例通过代理转换成 Invoker, 第二步会把 Invoker 通过具体的协议 ( 比如 Dubbo ) 转换成 Exporter,
详细:provider通过serviceConfig的export()方法,内部通过proxyFactory的getinvoker()获取invoker,然后调用protocol的export()方法,执行init()得到最后的exporter,最后注册到注册中心;
详细流程时序图:
发现引用:第一步通过持有远程服务实例生成Invoker, 这个 Invoker 在客户端是核心的远程代理对象 。 第二步会把 Invoker 通过动态代理转换成实现用户接口的动态代理引用
详细:consumer通过ReferenceConfig的refer()方法,内部开始对调用注册中心,订阅,然后调用Protocol 的refer(),执行init()取得invoker,然后通过ProxyFactory的getproxy()获得需要用的接口ref
详细流程时序图: