Spring父子上下文的使用案例

一、背景

最近在看在使用​​Spring Cloud​​​的时候发现,当我们通过​​Feign​​去调用别的微服务时,当我们有多个Feign客户端(比如:用户微服务、商品微服务)时,是可以为每个Feign客户端配置不同的实现,比如:用户微服务使用Feign默认的契约,而商品微服务可以使用Spring MVC 的契约格式,那么这个是怎么实现的呢?此处我们写一个简单的例子来模拟一下。

二、需求

假设我们存在一个 ​​CommonApi​​的接口,用户微服务(user)和我们的调用方分别实现这个接口,实现不同的功能,而我们的产品微服务(product)不实现这个接口,默认采用调用方的实现。

调用方(父上下文)
实现 CommonApi 接口,兜底实现,如果被调用方没实现,则采用这个,否则采用被调用方自己的逻辑。

user微服务(子上下文)
实现 CommonApi 接口

product微服务(子上下文)
不实现 CommonApi 接口。

在调用方,会同时调用 user微服务和product微服务 中的 CommonApi 接口,当被调用方自己实现了CommonApi接口时,使用被调用方自己的逻辑,如果被调用方没有实现,则使用调用方自己的逻辑。

即我们要实现的效果:

1、在调用方程序中,自己的上下文中获取到的 ​​CommonApi​​ 是调用方自己实现的。

2、在调用方程序中,使用 用户服务 的上下文中获取到的 ​​CommonApi​​ 是用户服务实现。

3、在调用方程序中,使用 商品服务 的上下文中获取到的 ​​CommonApi​​ 是调用方实现的,因为商品服务自己没有实现。

如果我们把 ​​CommonApi​​​理解为​​Feign​​​中的​​feign.Contract​​,那么在 用户服务 中就是我们修改了Feign默认的Contract,而 产品服务 就是使用的默认的Contract。

三、实现步骤

1、基础代码编写

Spring父子上下文的使用案例_Feign父子上下文原理

2、测试结果

Spring父子上下文的使用案例_Spring父子上下文_02

四、小彩蛋

​Spring Cloud OpenFeign​​中父子上下文的实现。

​FeignContext​​​ 实现了 ​​NamedContextFactory​​​接口,NamedContextFactory中有个​​org.springframework.cloud.context.named.NamedContextFactory#createContext​​方法,可以看到父子上下文是如何建立的。

Spring父子上下文的使用案例_Spring父子上下文案例_03

五、完整代码

代码链接:​​https://gitee.com/huan1993/spring-cloud-parent/tree/master/springboot/spring-parent-child-context​