首页 > 其他分享 >聊聊如何利用服务定位器模式按需返回我们需要的服务实例

聊聊如何利用服务定位器模式按需返回我们需要的服务实例

时间:2023-06-13 14:48:09浏览次数:40  
标签:定位器 args 服务 beanName private 聊聊 public

前言

什么是服务定位器模式

服务定位器是一个了解如何提供各种应用所需的服务(或组件)的对象。在服务定位器中,每个服务(或组件)都只有一个单独的实例,并通过ID 唯一地标识。 用这个 ID 就能从服务定位器中得到这个服务(或组件)。

何时可以考虑使用服务定位器模式

服务定位器模式的目的是按需返回服务实例,当依赖是按需的或需要在运行时查找时,我们可以使用服务定位器模式将客户端与具体实现解耦。

服务定位器包含的组件

  • 客户端:在运行时需要服务的消费者。
  • 服务定位器:服务定位器负责将服务按需返回给客户端。它抽象了服务的查找或创建。
  • 初始上下文:它创建、注册和缓存服务。这是查找和创建的起点。
  • 服务工厂: 服务工厂为服务提供生命周期管理,支持创建、查找或删除服务。
  • 服务:客户所需服务的具体实现。

服务定位器执行流程

下面我们就以一个模拟发送短信的例子,来体验一把服务定位器模式。因spring已经提供了服务定位器,本示例就以spring提供的服务定位器为例

前置知识

spring 服务定位器

spring的服务定位器主要是通过ServiceLocatorFactoryBean实现。它实现 FactoryBean接口,并封装了服务定位器模式的所有设计组件,为客户端提供了一个干净的 API 以按需获取对象

spring服务定位器实现流程

示例

1、定义一个实体类,这个实体类后边插件绑定具体短信服务会用到

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class SmsRequest implements Serializable {

    private Map<String,Object> metaDatas;

    private String to;

    private String message;

    private SmsType smsType;


}

2、定义短信发送服务接口

public interface SmsProvider {


    SmsResponse sendSms(SmsRequest smsRequest);


}

3、定义短信服务定位器工厂,用来选取具体的短信服务

public interface SmsFactory {

    SmsProvider getProvider(SmsType smsType);
}


4、定义短信发送具体实现类

@Component
public class AliyunSmsProvider implements SmsProvider {
    @Override
    public SmsResponse sendSms(SmsRequest smsRequest) {
        System.out.println("来自阿里云短信:" + smsRequest);
        return SmsResponse.builder()
                .code("200").message("发送成功")
                .success(true).result("阿里云短信的回执").build();
    }


}


注: 该具体服务必须是spring的bean

5、配置ServiceLocatorFactoryBean

 @Bean
    @ConditionalOnMissingBean
    public FactoryBean smsFactory(){
        ServiceLocatorFactoryBean serviceLocatorFactoryBean = new ServiceLocatorFactoryBean();
        serviceLocatorFactoryBean.setServiceLocatorInterface(SmsFactory.class);
        // spring beanName映射,自定义名称映射关系,
        Properties properties = new Properties();
        properties.setProperty(SmsType.ALIYUN.toString(),"aliyunSmsProvider");
        properties.setProperty(SmsType.TENCENT.toString(),"tencentSmsProvider");
        serviceLocatorFactoryBean.setServiceMappings(properties);
        return serviceLocatorFactoryBean;
    }

注: 短信服务定位器工厂,本质是通过beanName来找到具体的短信服务,如下示例

public interface SmsFactory {

    SmsProvider getProvider(String beanName);
}


但为了保持一定的业务语义,我们可以通过

   serviceLocatorFactoryBean.setServiceMappings(properties);

来实现业务类型-->beanName的映射

映射源码如下

	private String tryGetBeanName(@Nullable Object[] args) {
			String beanName = "";
			if (args != null && args.length == 1 && args[0] != null) {
				beanName = args[0].toString();
			}
			// Look for explicit serviceId-to-beanName mappings.
			if (serviceMappings != null) {
				String mappedName = serviceMappings.getProperty(beanName);
				if (mappedName != null) {
					beanName = mappedName;
				}
			}
			return beanName;
		}

6、业务如何使用

@RequiredArgsConstructor
public class SmsService {


    private final SmsFactory smsFactory;


    public SmsResponse sendSms(SmsRequest smsRequest){

        return smsFactory.getProvider(smsRequest.getSmsType()).sendSms(smsRequest);


    }
}

7、测试

 @Autowired
    private SmsService smsService;

    @Test
    public void testAliyunSms(){
        SmsRequest smsRequest = SmsRequest.builder()
                .message("模拟使用阿里云短信发送")
                .to("136000000001")
                .smsType(SmsType.ALIYUN)
                .build();

        SmsResponse smsResponse = smsService.sendSms(smsRequest);
        Assert.assertTrue(smsResponse.isSuccess());
        System.out.println(smsResponse);

    }

总结

眼尖的朋友可能会发现,你上面实现的服务定位器,用如下方法

   @Autowired
    private ApplicationContext applicationContext;


  

    @Override
    public void run(ApplicationArguments args) throws Exception {
        SmsProvider smsProvider = applicationContext.getBean("aliyunSmsProvider",SmsProvider.class);
        smsProvider.sendSms()
    }

也能实现,干嘛那么繁琐,如果你翻看源码,就会发现,他底层实现和上述的实现基本上一样

	private Object invokeServiceLocatorMethod(Method method, Object[] args) throws Exception {
			Class<?> serviceLocatorMethodReturnType = getServiceLocatorMethodReturnType(method);
			try {
				String beanName = tryGetBeanName(args);
				Assert.state(beanFactory != null, "No BeanFactory available");
				if (StringUtils.hasLength(beanName)) {
					// Service locator for a specific bean name
					return beanFactory.getBean(beanName, serviceLocatorMethodReturnType);
				}
				else {
					// Service locator for a bean type
					return beanFactory.getBean(serviceLocatorMethodReturnType);
				}
			}
			catch (BeansException ex) {
				if (serviceLocatorExceptionConstructor != null) {
					throw createServiceLocatorException(serviceLocatorExceptionConstructor, ex);
				}
				throw ex;
			}
		}

其实服务定位器模式和依赖注入都是控制反转概念的实现,服务定位器将一组职责相似的服务内聚到了一起,并实现服务提供方、服务使用方完全的解耦,上面举的例子也可以看成一种策略+工厂模式的具体实现。最后提一嘴,serviceLocatorFactoryBean.setServiceMappings(properties);这个也不是必须的,只要你业务语义和beanName名字一样即可

demo链接

https://github.com/lyb-geek/springboot-learning/tree/master/springboot-service-locator

标签:定位器,args,服务,beanName,private,聊聊,public
From: https://www.cnblogs.com/linyb-geek/p/17191368.html

相关文章

  • 4500字聊聊云原生数据库
    云计算的快速发展,打破了传统技术架构的高壁垒,加速创新技术的普及和应用,帮助企业减少信息基础设施投入、降低软硬件运维人力成本、消除软件合规问题、保障数据安全。在云计算大势的推动之下,数据库作为云计算关键技术和最基础的服务之一,同样需要不断进化以适应新的场景需求,“生于云,长......
  • mmhmm重塑视频会议、2020新款emoji可爱来袭、微软将推云游戏服务xCloud等| Decode the
    Social MediaSucks.DecodetheWeek≠音视频技术周刊 NewsBriefing1. Evernote前CEO推出虚拟摄影棚应用mmhmm重塑视频会议PhilLibin带领Evernote创造辉煌后,再次回到消费与企业应用的交界,推出虚拟相机云服务mmhmm(中文发音是“嗯哼”)。mmhmm可在Zoom、GoogleMeet、YouTube以......
  • 聊聊QUIC协议的发展
    作者|王盛策划|包研、Alex编辑|AlexQUIC年终盘点#001#QUIC(QuickUDPInternetConnections,快速UDP互联网连接)是一种新的“更快”的通用网络传输协议。相比于TCP和TLS,QUIC提供了许多改进来提升网络传输的性能。随着QUIC协议的标准化,QUIC之上的HTTP/3协议已经被众多浏览器所......
  • 如何使用开源SFU构建RTC云服务
    编者按:本文由百度智能云RTC产品技术负责人李永兴LiveVideoStack线上分享的内容整理而成,从系统架构角度,分析了常见的开源SFU在分布式部署以及高可用、高并发方面的不足,并提出相应的解决方案。大家好,我是来自百度智能云的李永兴,在百度智能云媒体云团队主要负责RTC产品的研发工作。01......
  • 媒体服务质量保障与QoE
    LiveVideoStackCon2022音视频技术大会北京站将于12月9日至10日在北京丽亭华苑酒店召开,本次大会将延续【音视频+无限可能】的主题,邀请业内众多企业及专家学者,将他们在过去一年乃至更长时间里对音视频在更多领域和场景下应用的探索、在实践中打磨优化技术的经验心得、对技术与商业......
  • TikTok推出招聘服务、 沃尔玛收购虚ekit、开源圆桌、AI新创Poised|拟试穿公司ZeDecode
     DecodetheWeek ≠音视频技术周刊 Credit:KekeLiang/NewsBriefing. Facebook正在失去社交媒体控制地位 Appfigures的最新数据显示,Facebook的应用在过去12个月的月度下载量越来越少, TikTok则已经超过了Facebook和其他公司,成为2020年下载量最多的应用。Facebook 应......
  • IBM Cloud:裸金属服务器+多云策略助力音视频解决方案成功出海
    到底什么是公有云、私有云和混合云?疫情给云服务厂商带来了哪些挑战?IBM是如何助力音视频解决方案成功出海的?“后疫情”时代音视频的下一个风口在哪里?对此,LiveVideoStack很荣幸地采访到了来自IBM云平台事业部,资深云计算架构师——胡磊,聊一聊他对这些问题的看法和观点。胡磊技术访谈#0......
  • 解密华为云原生媒体网络如何保障实时音视频服务质量
    随着5G和AI的发展,内容表达视频化成为了当今的主流,很多行业对视频分发有非常旺盛的需求。我们非常荣幸地请到了华为云的资深视频架构师黄挺,为大家介绍基于互联网的实时音视频服务所面临的挑战,分享华为云原生媒体网络全方位保障实时音视频服务体验的实践。文/黄挺整理/LiveVideoS......
  • 新的Azure通信服务(ACS)如何实现WebRTC?
    正文字数:3144 阅读时长:4分钟Housepaty的软件工程师GustavoGarcia,他对Azure通信服务(ACS)进行了全面的评估,包括从浏览器兼容性、编解码器到带宽估计算法…..与主要对手相比成熟度还有差距。文 / GustavoGarcia译 / HelenLyu原文链接/ https://webrtchacks.com/how-does-azu......
  • 聊聊Flink必知必会(二)
    Checkpoint与BarrierFlink是一个有状态的流处理框架,因此需要对状态做持久化,Flink定期保存状态数据到存储空间上,故障发生后从之前的备份中恢复,这个过程被称为Checkpoint机制。而Checkpoint为Flink提供了Exactly-Once的投递保障。流处理是一个数据不断输入的过程,为了更好更方便的......