JDK SPI机制及实现

设计目标

面向对象的设计里,模块与模块之间是通过接口通信的,模块之间不对实现类进行硬编码。一旦代码里涉及到了具体的实现类,就违反了可插拔的原则,如果需要替换一种实现,就需要修改代码。为了在实现模块装配的时候,不在模块里写死代码,需要一种服务的发现机制。java spi就是提供这样的一个机制:为了某个接口寻找服务实现的机制。有点像IOC的思想,就是讲装配的控制权移到代码之外。

具体约定

当服务的提供者(provider),提供了一个接口多种实现时,一般会在jar包的META-INF/services/目录下,创建改接口的同名文件(接口的全名),文件的内容为改接口的具体的实现类的名称。而当外部加载这个模块的时候,就通过jar包META-INF/services/里的配置文件得到具体的实现类名,并加载实例化,完成模块的装载。

DEMO

定义接口

package com.dodoi.jdk.spi;

public interface Command {
   public void execute();
}

实现类一

package com.dodoi.jdk.spi;

public class StartCommand implements Command{
   @Override
   public void execute() {
       System.out.println("command start");
   }
}

实现类二

package com.dodoi.jdk.spi;

public class ShutdownCommand implements Command{
   @Override
   public void execute() {
       System.out.println("command shutdown");
   }
}

META-INF/service/ com.dodoi.jdk.spi.Command

 com.dodoi.jdk.spi.StartCommand
com.dodoi.jdk.spi.ShutdownCommand

测试

package com.dodoi.jdk.spi;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

public class App {

  private static final Logger LOGGER = LoggerFactory.getLogger(App.class);

  /**
   * Executes the App
   */
  public App() {

    ServiceLoader<Command> serviceLoader = ServiceLoader.load(Command.class);
    for(Command command : serviceLoader){
      command.execute();
    }
  }

  /**
   * Program entry point
   *
   * @param args command line args
   */
  public static void main(String[] args) {
    new App();
  }

}

输出

command start
command shutdown

JDK SPI缺点

jdk会一次性加载所有的实现类

  • 启动耗时
  • 浪费资源
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值