一、spring-cloud-feign 中的代理模式
Feign 是 Spring cloud 微服务架构组件之一,Feign 功能主要是远程 API 调用。
Feign 相关使用案例代码如下:
上述 Feign APi 调用程序代码中,
存在两个服务,一个是 consumer
一个是 provider
。
consumer
通过Feign 发起远程调用,调用 provider
中的 API 接口 /hello/name
通过上述代码能够知道,consumer
发起远程 API 调用,代码直接是调用的 Feign Client 接口类 HelloClient
。
总结 Feign 案例代码信息能够得到三点:
1、远程服务名称 provider
2、远程 API 接口 /hello/name 3、代码定义的API调用,只是一个接口类
通过上述信息能够知道,Feign 需要通过这些信息发起远程 API 调用, Feign 需要做的就是将 provider
置换成 IP + port
的具体请求地址,然后结合 API 接口 /hello/name
拼接请求 url ,发起 HTTP 请求。
而完成这些功能的 Feign Client
也就是 HelloClient
只是一个接口,该接口只是做了方法的定义,而真正实现功能的是 Feign Client
的代理类。
以上述代码案例,Feign Client 接口,也就是 HelloClient
在进行实例化加入到 Spring IOC 容器时,会构建一个代理对象,该代理对象的逻辑图如下:
Feign Clicent 最终实例化的对象,有两部分内容需要关注:
HardCodedTarget
ReflectiveFeign.FeignInvocationHandler
分别来看一下 **HardCodedTarget**
对象 和 **ReflectiveFeign.FeignInvocationHandler**
HardCodedTarget
代码如下
该对象存储了远程调用的相关信息
- type :
存储的就是 Feign Client 类,也就是HelloClient
- name :
存储的就是远程服务名,也就是provider
- url :
存储的就是远程API调用,也就是http://provider
ReflectiveFeign.FeignInvocationHandler
如上述代码,该对象是典型的的 JDK 动态代理类,真正进行 请求发送的代码在该代理类中完成。
具体 Http 请求操作,在
`dispatch.get(method).invoke(args)
中完成。 其中 `dispatch.get(method)` 获取到的 对象为 `
SynchronousMethodHandler` ` 这里面包含了负载均衡,链路追踪等,自行进行扩展。
总结
在 SPring Cloud 中使用 Feign 组件进行远程API 调用,只需要定义 Feign Client 接口类就可以进行 API 调用,如下图:
其原理是因为,代码底层通过 JDK 动态代理,为 Feign Client
做了代理,所有操作都在代理中进行。
二、Mybatis 中 Mapper 接口动态代理
Mybatis 面试题中,最喜欢问的一个问题,XXXMapper.java
接口,只是一个接口,为什么直接调用就能够发起数据库请求?
Mybatis 中最重要的类就是 **Configuration**
,构建 Configuration
的类为 XMLConfigBuilder
,在进行 Configuration
构建的时候,相关的 **XXXMapper.java**
接口同样会被读取存储在 Configuration
中的 **MapperRegister**
。
MapperRegister
注册 Mapper.java
接口的相关代码如下:
在进行 XXXMapper.java
信息缓存的时候,Mybatis 真实缓存的是 **MapperProxyFactory**
类,代理工厂类。
来看看代理工厂类具体内容
如上述代码,直接根据 XXXMapper.java
接口进行代理类的创建,对应的代理类为 **MapperProxy**
,来看看代理类 MapperProxy
,具体查看其 invoke
方法,相关代码如下:
如上代码,**MapperProxy**
是一个 JDK 动态代理类,而在 **invoke**
方法中会调用 **MapperMethod#execute**
进行 SQL 语句的拼接调用。
总结
Mybatis 中针对每一个 XXXMapper.java
接口进行代理,相关逻辑图如下:
回到问题:为什么直接调用 XXXMapper.java
接口就能够进行 SQL 查询,因为在代码运行期间,XXXMapper.java
会被代理类 MapperProxy
代理,所有的操作都由 代理类来完成。
三、项目应用中的代理模式
Springframework AOP 本身实现就是 代理模式,项目中使用 springframework 框架时并用到了 AOP,就相当于使用了 代理。
【公众号】花好夜猿