getAttachments();
/**
* get attachment by key.
*
* @return attachment value.
* @serial
*/
String getAttachment(String key);
/**
* get attachment by key with default value.
*
* @return attachment value.
* @serial
*/
String getAttachment(String key, String defaultValue);
/**
* get the invoker in current context.
*
* @return invoker.
* @transient
*/
Invoker> getInvoker();
}
```
- `#getMethodName()` 方法,获得方法名。
- `#getParameterTypes()` 方法,获得方法参数**类型**数组。
- `#getArguments()` 方法,获得方法参数数组。
- `#getAttachments()`等方法,获得隐式参数相关。
- 不了解的胖友,可以看看 [《Dubbo 用户指南 —— 隐式参数》](http://dubbo.apache.org/zh-cn/docs/user/demos/attachment.html) 文档。
- 和 HTTP Request **Header** 有些相似。
- `#getInvoker()` 方法,获得对应的 Invoker 对象。
#### 4.2.1 类图
[![Invocation 子类](http://static2.iocoder.cn/images/Dubbo/2018_03_01/06.png)](http://static2.iocoder.cn/images/Dubbo/2018_03_01/06.png)Invocation 子类
- `com.alibaba.dubbo.rpc.RpcInvocation`
- 点击查看,比较容易理解。
- `com.alibaba.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation`
- Dubbo 协议**独有**,后续文章分享。
### 4.3 Result
[`com.alibaba.dubbo.rpc.Result`](https://github.com/YunaiV/dubbo/blob/6de0a069fcc870894e64ffd54a24e334b19dcb36/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/Result.java) 。Result 是会话域,它持有调用过程中返回值,异常等。
代码如下:
```
public interface Result {
/**
* Get invoke result.
*
* @return result. if no result return null.
*/
Object getValue();
/**
* Get exception.
*
* @return exception. if no exception return null.
*/
Throwable getException();
/**
* Has exception.
*
* @return has exception.
*/
boolean hasException();
/**
* Recreate.
*
*
* if (hasException()) {
* throw getException();
* } else {
* return getValue();
* }
*
*
* @return result.
* @throws if has exception throw it.
*/
Object recreate() throws Throwable;
/**
* get attachments.
*
* @return attachments.
*/
Map getAttachments();
/**
* get attachment by key.
*
* @return attachment value.
*/
String getAttachment(String key);
/**
* get attachment by key with default value.
*
* @return attachment value.
*/
String getAttachment(String key, String defaultValue);
}
```
- `#getValue()` 方法,获得返回值。
- `#getException()`方法,获得返回的异常。
- `#hasException()` 方法,是否有异常。
- `#recreate()` 方法,实现代码如下:
```
// RpcResult.java
private Object result;
private Throwable exception;
public Object recreate() throws Throwable {
if (exception != null) {
throw exception;
}
return result;
}
```
- `#getAttachments()` 等方法,获得**返回**的隐式参数相关。
- 不了解的胖友,可以看看 [《Dubbo 用户指南 —— 隐式参数》](http://dubbo.apache.org/zh-cn/docs/user/demos/attachment.html) 文档。
- 和 HTTP Response **Header** 有些相似。
#### 4.3.1 类图
[![Invocation 子类](http://static2.iocoder.cn/images/Dubbo/2018_03_01/07.png)](http://static2.iocoder.cn/images/Dubbo/2018_03_01/07.png)Invocation 子类
- `com.alibaba.dubbo.rpc.RpcResult`
- 点击查看,比较容易理解。
- `com.alibaba.dubbo.rpc.protocol.dubbo.DecodeableRpcResult`
- Dubbo 协议**独有**,后续文章分享。
### 4.4 Filter
[`com.alibaba.dubbo.rpc.Filter`](https://github.com/YunaiV/dubbo/blob/6de0a069fcc870894e64ffd54a24e334b19dcb36/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/Filter.java) 。过滤器接口,和我们平时理解的 [`javax.servlet.Filter`](https://docs.oracle.com/javaee/5/api/javax/servlet/Filter.html) 基本一致。
代码如下:
```
public interface Filter {
/**
* do invoke filter.
*
*
* // before filter
* Result result = invoker.invoke(invocation);
* // after filter
* return result;
*
*
* @param invoker service
* @param invocation invocation.
* @return invoke result.
* @throws RpcException
* @see com.alibaba.dubbo.rpc.Invoker#invoke(Invocation)
*/
Result invoke(Invoker> invoker, Invocation invocation) throws RpcException;
}
```
- `#invoke(...)` 方法,执行 Invoker 的过滤逻辑。代码示例如下:
```
// 【自己实现】before filter
Result result = invoker.invoke(invocation);
// 【自己实现】after filter
return result;
```
#### 4.4.1 类图
[![Filter 子类](http://static2.iocoder.cn/images/Dubbo/2018_03_01/08.png)](http://static2.iocoder.cn/images/Dubbo/2018_03_01/08.png)Filter 子类
### 4.5 ProxyFactory
[`com.alibaba.dubbo.rpc.ProxyFactory`](https://github.com/YunaiV/dubbo/blob/6de0a069fcc870894e64ffd54a24e334b19dcb36/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/ProxyFactory.java) ,代理工厂接口。
代码如下:
```
@SPI("javassist")
public interface ProxyFactory {
/**
* create proxy.
*
* 创建 Proxy ,在引用服务调用。
*
* @param invoker
* @return proxy
*/
@Adaptive({Constants.PROXY_KEY})
T getProxy(Invoker invoker) throws RpcException;
/**
* create invoker.
*
* 创建 Invoker ,在暴露服务时调用。
*
* @param
* @param proxy
* @param type
* @param url
* @return invoker
*/
@Adaptive({Constants.PROXY_KEY})
Invoker getInvoker(T proxy, Class type, URL url) throws RpcException;
}
```
- `#getProxy(invoker)` 方法,创建 Proxy ,在**引用服务**时调用。
- 方法参数如下:
- `invoker` 参数,Consumer 对 Provider 调用的 Invoker 。
- 服务消费着引用服务的 **主过程** 如下图:
> FROM [《Dubbo 开发指南 —— 实现细节》](http://dubbo.apache.org/zh-cn/docs/dev/)
> [![服务消费着引用服务的主过程](http://static2.iocoder.cn/images/Dubbo/2018_03_01/12.png)](http://static2.iocoder.cn/images/Dubbo/2018_03_01/12.png)服务消费着引用服务的主过程
- 从图中我们可以看出,方法的 `invoker` 参数,通过 Protocol 将 **Service接口** 创建出 Invoker 。
- 通过创建 Service 的 Proxy ,实现我们在业务代理调用 Service 的方法时,**透明的内部转换成调用** Invoker 的 `#invoke(Invocation)` 方法。🙂 如果还是比较模糊,木有关系,后面会有文章,专门详细代码的分享。
- `#getInvoker(proxy, type, url)` 方法,创建 Invoker ,在**暴露服务**时调用。
- 方法参数如下:
- `proxy` 参数,Service 对象。
- `type` 参数,Service 接口类型。
- `url` 参数,Service 对应的 Dubbo URL 。
- 服务提供者暴露服务的 **主过程** 如下图:
> FROM [《Dubbo 开发指南 —— 实现细节》](http://dubbo.apache.org/zh-cn/docs/dev/)
> [![服务提供者暴露服务的主过程](http://static2.iocoder.cn/images/Dubbo/2018_03_01/11.png)](http://static2.iocoder.cn/images/Dubbo/2018_03_01/11.png)服务提供者暴露服务的主过程
- 从图中我们可以看出,该方法创建的 Invoker ,下一步会提交给 Protocol ,从 Invoker 转换到 Exporter 。
#### 4.5.1 类图
[![ProxyFactory 子类](http://static2.iocoder.cn/images/Dubbo/2018_03_01/13.png)](http://static2.iocoder.cn/images/Dubbo/2018_03_01/13.png)ProxyFactory 子类
从图中,我们可以看出 Dubbo 支持 Javassist 和 JDK Proxy 两种方式生成代理。
具体如何实现,请看后面的文章。
## 4.6 Protocol
[`com.alibaba.dubbo.rpc.Protocol`](https://github.com/YunaiV/dubbo/blob/6de0a069fcc870894e64ffd54a24e334b19dcb36/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/Protocol.java) 。
> Protocol 是服务域,它是 Invoker 暴露和引用的主功能入口。
> 它负责 Invoker 的生命周期管理。
代码如下:
```
@SPI("dubbo")
public interface Protocol {
/**
* Get default port when user doesn't config the port.
*
* @return default port
*/
int getDefaultPort();
/**
* Export service for remote invocation:
* 1. Protocol should record request source address after receive a request:
* RpcContext.getContext().setRemoteAddress();
* 2. export() must be idempotent, that is, there's no difference between invoking once and invoking twice when
* export the same URL
* 3. Invoker instance is passed in by the framework, protocol needs not to care
*
* @param Service type
* @param invoker Service invoker
* @return exporter reference for exported service, useful for unexport the service later
* @throws RpcException thrown when error occurs during export the service, for example: port is occupied
*/
/**
* 暴露远程服务:
* 1. 协议在接收请求时,应记录请求来源方地址信息:RpcContext.getContext().setRemoteAddress();
* 2. export() 必须是幂等的,也就是暴露同一个 URL 的 Invoker 两次,和暴露一次没有区别。
* 3. export() 传入的 Invoker 由框架实现并传入,协议不需要关心。
*
* @param 服务的类型
* @param invoker 服务的执行体
* @return exporter 暴露服务的引用,用于取消暴露
* @throws RpcException 当暴露服务出错时抛出,比如端口已占用
*/
@Adaptive
Exporter export(Invoker invoker) throws RpcException;
/**
* Refer a remote service:
* 1. When user calls `invoke()` method of `Invoker` object which's returned from `refer()` call, the protocol
* needs to correspondingly execute `invoke()` method of `Invoker` object
* 2. It's protocol's responsibility to implement `Invoker` which's returned from `refer()`. Generally speaking,
* protocol sends remote request in the `Invoker` implementation.
* 3. When there's check=false set in URL, the implementation must not throw exception but try to recover when
* connection fails.
*
* @param Service type
* @param type Service class
* @param url URL address for the remote service
* @return invoker service's local proxy
* @throws RpcException when there's any error while connecting to the service provider
*/
/**
* 引用远程服务:
* 1. 当用户调用 refer() 所返回的 Invoker 对象的 invoke() 方法时,协议需相应执行同 URL 远端 export() 传入的 Invoker 对象的 invoke() 方法。
* 2. refer() 返回的 Invoker 由协议实现,协议通常需要在此 Invoker 中发送远程请求。
* 3. 当 url 中有设置 check=false 时,连接失败不能抛出异常,并内部自动恢复。
*
* @param 服务的类型
* @param type 服务的类型
* @param url 远程服务的URL地址
* @return invoker 服务的本地代理
* @throws RpcException 当连接服务提供方失败时抛出
*/
@Adaptive
Invoker refer(Class type, URL url) throws RpcException;
/**
* Destroy protocol:
* 1. Cancel all services this protocol exports and refers
* 2. Release all occupied resources, for example: connection, port, etc.
* 3. Protocol can continue to export and refer new service even after it's destroyed.
*/
/**
* 释放协议:
* 1. 取消该协议所有已经暴露和引用的服务。
* 2. 释放协议所占用的所有资源,比如连接和端口。
* 3. 协议在释放后,依然能暴露和引用新的服务。
*/
void destroy();
}
```
- 每个方法的说明,请**细看**方法的注释。
> Dubbo 处理**服务暴露**的关键就在 Invoker 转换到 Exporter 的过程。
> 下面我们以 Dubbo 和 RMI 这两种典型协议的实现来进行说明:
>
> - **Dubbo 的实现**
> Dubbo 协议的 Invoker 转为 Exporter 发生在 DubboProtocol 类的 export 方法,它主要是打开 socket 侦听服务,并接收客户端发来的各种请求,通讯细节由 Dubbo 自己实现。
> - **RMI 的实现**
> RMI 协议的 Invoker 转为 Exporter 发生在 RmiProtocol 类的 export 方法,它通过 Spring 或 Dubbo 或 JDK 来实现 RMI 服务,通讯细节这一块由 JDK 底层来实现,这就省了不少工作量。
#### 4.6.1 类图
[![Protocol 子类](http://static2.iocoder.cn/images/Dubbo/2018_03_01/14.png)](http://static2.iocoder.cn/images/Dubbo/2018_03_01/14.png)Protocol 子类
从图中,我们可以看出 Dubbo 支持多种协议的实现。
具体如何实现,请看后面的文章。
### 4.7 Exporter
[`com.alibaba.dubbo.rpc.Exporter`](https://github.com/YunaiV/dubbo/blob/6de0a069fcc870894e64ffd54a24e334b19dcb36/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/Exporter.java) 。
Exporter ,Invoker 暴露服务在 Protocol 上的对象。
代码如下:
```
public interface Exporter {
/**
* get invoker.
*
* @return invoker
*/
Invoker getInvoker();
/**
* unexport.
*
*
* getInvoker().destroy();
*
*/
void unexport();
}
```
- `#getInvoker()` 方法,获得对应的 Invoker 。
- `#unexport()`方法,取消暴露。
- Exporter 相比 Invoker 接口,多了 **这个方法**。通过实现该方法,使**相同**的 Invoker 在**不同**的 Protocol 实现的取消暴露逻辑。
#### 4.7.1 类图
[![Exporter 子类](http://static2.iocoder.cn/images/Dubbo/2018_03_01/15.png)](http://static2.iocoder.cn/images/Dubbo/2018_03_01/15.png)Exporter 子类
具体如何实现,请看后面的文章。
### 4.8 InvokerListener
[`com.alibaba.dubbo.rpc.InvokerListener`](https://github.com/YunaiV/dubbo/blob/6de0a069fcc870894e64ffd54a24e334b19dcb36/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/InvokerListener.java) ,Invoker 监听器。
代码如下:
```
@SPI
public interface InvokerListener {
/**
* The invoker referred
*
* 当服务引用完成
*
* @param invoker
* @throws RpcException
* @see com.alibaba.dubbo.rpc.Protocol#refer(Class, URL)
*/
void referred(Invoker> invoker) throws RpcException;
/**
* The invoker destroyed.
*
* 当服务销毁引用完成
*
* @param invoker
* @see com.alibaba.dubbo.rpc.Invoker#destroy()
*/
void destroyed(Invoker> invoker);
}
```
#### 4.8.1 类图
[![InvokerListener 子类](http://static2.iocoder.cn/images/Dubbo/2018_03_01/16.png)](http://static2.iocoder.cn/images/Dubbo/2018_03_01/16.png)InvokerListener 子类
### 4.9 ExporterListener
[`com.alibaba.dubbo.rpc.ExporterListener`](https://github.com/YunaiV/dubbo/blob/6de0a069fcc870894e64ffd54a24e334b19dcb36/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/ExporterListener.java) ,Exporter 监听器。
代码如下:
```
@SPI
public interface ExporterListener {
/**
* The exporter exported.
*
* 当服务暴露完成
*
* @param exporter
* @throws RpcException
* @see com.alibaba.dubbo.rpc.Protocol#export(Invoker)
*/
void exported(Exporter> exporter) throws RpcException;
/**
* The exporter unexported.
*
* 当服务取消暴露完成
*
* @param exporter
* @throws RpcException
* @see com.alibaba.dubbo.rpc.Exporter#unexport()
*/
void unexported(Exporter> exporter);
}
```
#### 4.9.1 类图
[![ExporterListener 子类](http://static2.iocoder.cn/images/Dubbo/2018_03_01/17.png)](http://static2.iocoder.cn/images/Dubbo/2018_03_01/17.png)ExporterListener 子类