• Java SPI 机制


    什么是 SPI

    SPI 全称为 (Service Provider Interface) ,是JDK内置的一种服务提供发现机制。可以将服务接口与服务实现分离以达到解耦可拔插、大大提升了程序可扩展性。

    1、制定统一的规范

    2、服务提供商提供这个规范具体的实现,在自己 jar 包的 META-INF/services/ 目录里创建一个以服务接口命名的文件,内容是实现类的全命名

    3、平台引入外部模块的时候,就能通过该jar包 META-INF/services/ 目录下的配置文件找到该规范具体的实现类名,然后装载实例化,完成该模块的注入。

    Java SPI 应用实例

    定义接口

    package com.demo.lin.spi;
    
    /**
     * @author Lin = ̄ω ̄=
     */
    public interface Download {
    	void download(String url);
    }
    
    

    实现类

    package com.demo.lin.spi.impl;
    
    import com.demo.lin.spi.Download;
    
    /**
     * @author Lin = ̄ω ̄=
     */
    public class FileDownload implements Download {
    
    	@Override
    	public void download(String url) {
    		System.out.println("download " + url);
    	}
    }
    
    

    配置

    com.demo.lin.spi.Download 内容

    com.demo.lin.spi.impl.FileDownload
    

    调用

    package com.demo.lin.spi;
    
    import java.util.ServiceLoader;
    
    /**
     * @author Lin = ̄ω ̄=
     */
    public class TestDemo {
    
    	public static void main(String[] args) {
    		ServiceLoader<Download> searches = ServiceLoader.load(Download.class);
    		for (Download search : searches) {
    			search.download("https://www.bilibili.com/video/BV1Vt4y1D7v8");
    		}
    	}
    }
    
    

    输出

    Java SPI 的用途

    其中一个典型案例就是 java.sql.Driver

    java.sql.Driver 定义了一个接口,并没有具体实现,具体的实现都是由不同厂商来提供的。

    当我们想连接 Mysql 时,引入 jar 包如 mysql-connector-java-5.1.45.jar,在 META-INF/services 目录下会有一个名字为 java.sql.Driver 的文件:

    com.mysql.jdbc.Driver
    com.mysql.fabric.jdbc.FabricMySQLDriver
    

    我们在代码中写到

    String url = "jdbc:mysql://localhost:3306/test";
    Connection conn = DriverManager.getConnection(url,username,password);
    

    DriverManager 内部使用 ServiceLoader.load(Driver.class),搜索 classpath 下以及 jar 包中所有的 META-INF/services 目录下的java.sql.Driver 文件,并找到文件中的实现类的名字,实例化具体的实现类。

    Spring SPI机制

    Spring 的 SPI 机制主要体现在 SpringBoot 中,当我们启动 SpringBoot 的 run() 方法,会调用类 SpringFactoriesLoader 下的 loadSpringFactories 方法,去加载 META-INF/spring.factories 下的配置。

    public final class SpringFactoriesLoader {
    
    	/**
    	 * The location to look for factories.
    	 * <p>Can be present in multiple JAR files.
    	 */
    	public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
    	
        // ...
        
        private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
    		MultiValueMap<String, String> result = cache.get(classLoader);
    		if (result != null) {
    			return result;
    		}
    
    		try {
    			Enumeration<URL> urls = (classLoader != null ?
    					classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
    					ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
                // ...
            }
            // ...
        }
    }
    
  • 相关阅读:
    DALSA线阵相机调焦、平场校正、行频微调
    千兆网卡、万兆网卡设置
    【转载】.h头文件 .lib库文件 .dll动态库文件之间的关系,静态编译、动态编译
    【转载】工控机插槽
    镜头的选择
    相机SDK流程
    光栅尺触发DALSA线阵相机
    Go语言备忘录(3):net/http包的使用模式和源码解析
    Go语言备忘录(2):反射的原理与使用详解
    Go语言备忘录(1):基本数据结构
  • 原文地址:https://www.cnblogs.com/linyuhong/p/14785123.html
Copyright © 2020-2023  润新知