spring-cloud-commons 中参考了 spring-cloud-netflix 的设计,引入了 NamedContextFactory 机制,一般用于对于不同微服务的客户端模块使用不同的 子 ApplicationContext 进行配置。
spring-cloud-commons 是 Spring Cloud 对于微服务基础组件的抽象。在一个微服务中,调用微服务 A 与调用微服务 B 的配置可能不同。比较简单的例子就是,A 微服务是一个简单的用户订单查询服务,接口返回速度很快,B 是一个报表微服务,接口返回速度比较慢。这样的话我们就不能对于调用微服务 A 和微服务 B 使用相同的超时时间配置。还有就是,我们可能对于服务 A 通过注册中心进行发现,对于服务 B 则是通过 DNS 解析进行服务发现,所以对于不同的微服务我们可能使用不同的组件,在 Spring 中就是使用不同类型的 Bean。
在这种需求下,不同微服务的客户端有不同的以及相同的配置,有不同的 Bean,也有相同的 Bean。所以,我们可以针对每一个微服务将他们的 Bean 所处于 ApplicationContext 独立开来,不同微服务客户端使用不同的 ApplicationContext。NamedContextFactory 就是用来实现这种机制的。
通过实例了解 NamedContextFactory 的使用
编写源码:
package com.github.hashjang.spring.cloud.iiford.service.common;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.cloud.context.named.NamedContextFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import java.util.List;
import java.util.Objects;
public class CommonNameContextTest {
private static final String PROPERTY_NAME = "test.context.name";
@Test
public void test() {
//创建 parent context
AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext();
//添加 BaseConfig 相关配置
parent.register(BaseConfig.class);
//初始化 parent
parent.refresh();
//创建 testClient1,默认配置使用 ClientCommonConfig
TestClient testClient1 = new TestClient(ClientCommonConfig.class);
//创建 service1 与 service2 以及指定对应额外的配置类
TestSpec testSpec1 = new TestSpec("service1", new Class[]{
Service1Config1.class, Service1Config2.class});
TestSpec testSpec2 = new TestSpec("service2", new Class[]{
Service2Config.class});
//设置 parent ApplicationContext 为 parent
testClient1.setApplicationContext(parent);
//将 service1 与 service2 的配置加入 testClient1
testClient1.setConfigurations(List.of(testSpec1, testSpec2));
BaseBean baseBean = testClient1.getInstance("service1", BaseBean.class);
System.out.println(baseBean);
//验证正常获取到了 baseBean
Assert.assertNotNull(baseBean);
ClientCommonBean commonBean = testClient1.getInstance("service1", ClientCommonBean.class