java SPI实战

  SPI 英文为 Service Provider Interface ,即服务提供者接口,SPI 将服务接口和具体的服务实现分离开来,将服务调用方和服务实现者解耦,能够提升程序的扩展性、可维护性。修改或者替换服务实现并不需要修改调用方。java很多优良的开源框架都使用了spi机制。话不多说,直接上实战代码。

       场景介绍,公司开发了一套支付的中间服务,分支持支付宝支付、微信支付、银联支付,而公司的产品有微信公众号、支付宝生活号,在微信公众号中不需要支付宝支付,在支付宝生活号中不需要使用微信支付,由于在不同的客户端需要的支付方式不一样,那么在调用支付中间件的时候,怎么实现热插拔,按需调用支付是必须考虑的问题,而spi机制就是解决这种场景问题的不二之选。

  1、创建支付服务的starter (pay-service-spring-boot-starter)项目

  2、pom文件添加场景启动器依赖

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
</dependency>

3、定义支付接口

public interface IPayService {
    String  pay(String  goods,float  fee);
}

4、支付实现

(1)支付宝支付

public class AliPayService   implements IPayService {
    @Override
    public String pay(String goods, float fee) {
        return  new Date()+"[支付宝支付成功"+fee+",您已经成功购买"+goods+"]";
    }
}

(2)微信支付

public class WechatPayService implements IPayService {
   @Override
    public String pay(String goods, float fee) {
       return  new Date()+"[微信支付成功"+fee+",您已经成功购买"+goods+"]";
    }
}

(3)银联支付

public class UnionPayService implements IPayService {
    @Override
    public String pay(String goods, float fee) {
        return  new Date()+"[银联支付成功"+fee+",您已经成功购买"+goods+"]";
    }
}

  (4)支付异常

public class ErrorPayService implements IPayService {
    @Override
    public String pay(String goods, float fee) {
        return "服务出现异常,无法正常支付";
    }
}

(5)定义支付类型

public enum PayWayEnum {
    /**
     * 支付类型
     */
    ALI("zfb"),

    WECHAT("wx"),

    UNION("union");

    private String  name;

    PayWayEnum(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

5、支付服务自动配

@ConfigurationProperties(prefix = "spi.pay.way")
public class PayWayProperties {
    /**
     * 支付宝: zfb   微信:wx  银联:union
     */
    private String  payName;
    
}
@Configuration
@ConditionalOnMissingBean(IPayService.class)
@EnableConfigurationProperties(PayWayProperties.class)
public class PayServiceAutoConfigure {

    @Bean
    public  IPayService  payService(PayWayProperties payWayProperties){
        ServiceLoader<IPayService> iPayServiceServiceLoader = ServiceLoader.load(IPayService.class);
        Iterator<IPayService> iterator = iPayServiceServiceLoader.iterator();
        IPayService  payService=null;
        String payName = payWayProperties.getPayName();
        while (iterator.hasNext()){
            payService =  iterator.next();
            if(payService instanceof AliPayService  &&  PayWayEnum.ALI.getName().equals(payName)){
                break;
            }
            if(payService instanceof WechatPayService  &&  PayWayEnum.WECHAT.getName().equals(payName)){
                break;
            }
            if(payService instanceof UnionPayService &&  PayWayEnum.UNION.getName().equals(payName)){
                break;
            }
        }
        if(payService==null){
            payService =new ErrorPayService();
        }
        return payService;
    }
}

6、配置spring.factories和spi文件

    在resources目录下创建META-INF目录,在META-INF目录下创建services目录,目录文件结构如下:

 spring.factories文件的内容:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  org.cn.fcw.service.config.PayServiceAutoConfigure

 spi配置文件org.cn.fcw.service.IPayService(文件使用支付接口的全路径命名),内容为具体实现类的全路径

org.cn.fcw.service.impl.UnionPayService
org.cn.fcw.service.impl.AliPayService
org.cn.fcw.service.impl.WechatPayService

   7、测试使用

       创建测试过程

    (1)pom加入依赖

<dependency>
    <groupId>org.cn.fcw</groupId>
    <artifactId>pay-service-spring-boot-starter</artifactId>
    <version>1.0</version>
 </dependency>

     (2)application.yml加入配置,选择具体的支付方式

spi:
  pay:
    way:
      #根据具体的需要选择  zfb 、wx 、 union
      payName: zfb

     (3)测试调用

@RunWith(SpringRunner.class)
@SpringBootTest
public class AppTest {

    @Autowired
    private IPayService payService;

    @Test
    public  void  payTest(){
        String res = payService.pay("苹果", 56.6f);
        System.out.println("res-------"+res);
    }

}

   输出结果:

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值