Java ServiceLoader、Spring SpringFactoriesLoader、SPI方式解耦第三方组件

8 篇文章 0 订阅
本文介绍了如何通过SPI(Service Provider Interface)来降低框架对第三方组件的侵入性,确保组件变更时对框架的影响减至最低。文章详细阐述了SPI的实现步骤,包括接口定义、服务加载工具类、接口实现以及配置文件设置,并提供了Java和Spring的SPI加载方式。通过这种方式,可以实现更灵活的服务提供者加载,并简化框架的升级和运维工作。
摘要由CSDN通过智能技术生成

背景

项目框架中引入了各种第三方组件,比如nacos、seata、mq、Redis、MySQL等等,这些三方组件一般都具有可替代性,如果把这些组件拿来直接使用会对原框架有一定侵入性,后期可能造成框架升级困难、运维复杂等多方面的问题。

使用SPI可以有效解耦三方组件,降低组件变更对原框架的影响,SPI需要原项目框架把可能用到的三方组件的功能抽象出接口,然后不同的组件按照SPI规范提供对应实现,完成对原项目框架的升级拓展。

实现

接口项目

SPI接口

由框架项目抽象出功能接口,例:

package com.test.spi;

public interface IHelloService {
	void sayHello(String name);
}

SPI接口工具类

通过这个工具类获取SPI接口的实现类,例:

package com.test.spi;

import java.util.List;
import java.util.ServiceLoader;

import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.util.CollectionUtils;

public class HelloServiceBuild {

	private static IHelloService service;

	public static IHelloService build() {
		if (null != service) {
			return service;
		}

		ServiceLoader<IHelloService> serviceLoader = ServiceLoader.load(IHelloService.class);
		if (serviceLoader.iterator().hasNext()) {
			service = serviceLoader.iterator().next();
		}

		if (null == service) {
			List<IHelloService> loadFactories = SpringFactoriesLoader.loadFactories(IHelloService.class, Thread.currentThread().getContextClassLoader());
			if (!CollectionUtils.isEmpty(loadFactories)) {
				service = loadFactories.get(0);
			}
		}

		return service;
	}
}

其中ServiceLoader是java自带获取SPI的方式,SpringFactoriesLoader是有spring提供的获取SPI的方式,可以看出这两种方式都会获取到一个SPI实例的集合,本例只获取集合中的第一个服务实例,两种方式都没有提供通过类名或者是其他方式获取某一确定实例的方式,需要自己拓展,可以参考dubbo的SPI实现过程。

服务项目

接口实现类

是SPI接口的具体实现,最终上面的工具类会实例化出这个类,通过该类完成业务调用,例:

package com.test.spi.provider;

import com.test.spi.IHelloService;

public class HelloServiceProvider implements IHelloService {
    @Override
    public void sayHello(String name) {
        System.out.println("Hello " + name);
    }
}

接口配置文件

SPI要完成自动加载实现类,需要借助配置文件,java和spring的配置方式不同,二选一留一个配置即可。

Java配置方式

需要在项目的META-INF/services目录下创建文件名为SPI接口全称的文件,例:

com.test.spi.IHelloService

文件内容为接口实现类的全名

com.test.spi.provider.HelloServiceProvider

Spring配置方式

需要在项目的META-INF目录下创建文件名为spring.factories的文件,

文件内容为SPI接口全名=SPI实现类全名

com.test.spi.IHelloService=com.test.spi.provider.HelloServiceProvider

使用SPI

SPI服务项目一般都是jar包,打包的时候需要确保META-INF文件夹及里面的内容在jar包里, 

使用时通过build获取服务提供者

IHelloService service = HelloServiceBuild.build();

if(null != service){
    service.sayHello("luck");
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值