Java-SPI从入门到实战


SPI全称为Service Provider Interface,是JDK内置的一种服务提供发现机制。简单来说,它就是一种动态替换发现机制。例如:有个接口想在运行时才发现具体的实现类,那么你只需要在程序运行前添加一个实现即可,并把新加的实现 描述给JDK即可。此外,在程序的运行过程中,也可以随时对该描述进行修改,完成具体实现的替换。

Java提供了很多服务提供者接口(Service Provider Interface,SPI),允许第三方为这些接口提供实现。常见的SPI有JDBC、JCE、JNDI、JAXP和JBI等。

这些SPI的接口是由Java核心库来提供,而SPI的实现则是作为Java应用所依赖的jar包被包含进类路径(CLASSPATH)中。例如:JDBC的实现mysql就是通过maven被依赖进来。

存在的问题

SPI的接口是Java核心库的一部分,是由引导类加载器(Bootstrap Classloader)来加载的。SPI的实现类是由系统类加载器(System ClassLoader)来加载的。

引导类加载器在加载时是无法找到SPI的实现类的,因为双亲委派模型中规定,引导类加载器BootstrapClassloader无法委派系统类加载器AppClassLoader来加载。这时候,该如何解决此问题?

线程上下文类加载由此诞生,它的出现也破坏了类加载器的双亲委派模型,使得程序可以进行逆向类加载。

主要关注点

  • 必须是接口全路径
    在这里插入图片描述

案例实战

在这里插入图片描述

定义接口

package com;
public interface HelloService {
    void hello();
}

实现类

package com.impl;
import com.HelloService;

public class HelloService1Impl implements HelloService {
    @Override
    public void hello() {
        System.out.println("com.HelloService world");
    }
}
package com.impl;
import com.HelloService;

public class HelloService2Impl implements HelloService {
    @Override
    public void hello() {
        System.out.println("com.HelloService world 2");
    }
}
package com;
import java.util.ServiceLoader;

public class Test {
    public static void main(String[] args) {
        ServiceLoader<HelloService> loaders = ServiceLoader.load(HelloService.class);
        for(HelloService helloService : loaders){
           helloService.hello();
        }
    }
}

配置文件

com.impl.HelloService1Impl
com.impl.HelloService2Impl

测试结果

在这里插入图片描述
来源:https://www.jianshu.com/p/e4262536000d

发布了60 篇原创文章 · 获赞 1 · 访问量 3316

猜你喜欢

转载自blog.csdn.net/qq_16438883/article/details/103919609
今日推荐