TOP

Java编程技术之浅析SPI服务发现机制(一)
2020-05-09 06:12:10 】 浏览:35次 本网站的内容取自网络,仅供学习参考之用,绝无侵犯任何人知识产权之意。如有侵犯请您及时与本人取得联系,万分感谢。
Tags:Java 编程 技术 浅析 SPI 服务 发现 机制

SPI服务发现机制

SPI是Java JDK内部提供的一种服务发现机制。

  • SPI->Service Provider Interface,服务提供接口,是Java JDK内置的一种服务发现机制

  • 通过在ClassPath路径下的META-INF/services文件夹查找文件,自动加载文件里所定义的类

[??注意事项]:
面向对象的设计里,一般推荐模块之间基于接口编程,模块之间不对实现类进行编码。如果涉及实现类就会违反可插拔的原则,针对于模块装配,Java SPI提供了为某个接口寻找服务的实现机制。

SPI规范

  • 使用约定:
    [1].编写服务提供接口,可以是抽象接口和函数接口,JDK1.8之后推荐使用函数接口

[2].在jar包的META-INF/services/目录里创建一个以服务接口命名的文件。其实就是实现该服务接口的具体实现类。

提供一个目录:
META-INF/services/
放到ClassPath下面

[3].当外部程序装配这个模块的时候,就能通过该Jar包META-INF/services/配置文件找到具体的实现类名,并装载实例化,完成模块注入。

目录下放置一个配置文件:
文件名是需要拓展的接口全限定名称
文件内部为要实现的接口实现类
文件必须为UTF-8编码

[4].寻找服务接口实现,不用在代码中提供,而是利用JDK提供服务查找工具类:java.util.ServiceLoader类来加载使用:

ServiceLoader.load(xxx.class)
ServiceLoader<XXXInterface> loads = ServiceLoader.load(xxx.class)

SPI源码分析

[1].ServiceLoader源码:
YMEMlV.png

package java.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.AccessController;
import java.security.AccessControlContext;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;

public final class ServiceLoader<S> implements Iterable<S>
{
    //[1].初始化定义全局配置文件路径Path
    private static final String PREFIX = "META-INF/services/";
    //[2].初始化定义加载的服务类或接口
    private final Class<S> service;
    //[3].初始化定义类加载器
    private final ClassLoader loader;
    //[4].初始化定义访问控制上下文
    private final AccessControlContext acc;
    //[5].初始化定义加载服务类的缓存集合 
    private LinkedHashMap<String,S> providers = new LinkedHashMap<>();
    //[6].初始化定义私有内部LazyIterator类,真正加载服务类的实现类
    private LazyIterator lookupIterator;
    
    //私有化有参构造-> ServiceLoader(Class<S> svc, ClassLoader cl)
    private ServiceLoader(Class<S> svc, ClassLoader cl) {   //[1].实例化服务接口->Class<S>
    service = Objects.requireNonNull(svc, "Service interface cannot be null");
    //[2].实例化类加载器->ClassLoader
    loader = (cl == null) ? ClassLoader.getSystemClassLoader() : cl;
    //[3].实例化访问控制上下文->AccessControlContext
    acc = (System.getSecurityManager() != null) ? AccessController.getContext() : null;
    //[4].回调函数->reload
    reload();
    }
    
    public void reload() {
    //[1].清空缓存实例集合
    providers.clear();
    //[2].实例化私有内部LazyIterator类->LazyIterator
    lookupIterator = new LazyIterator(service, loader);
    }
    
    public static <S> ServiceLoader<S> load(Class<S> service,ClassLoader loader)
    {
     return new ServiceLoader<>(service, loader);
    }
    
    public static <S> ServiceLoader<S> load(Class<S> service) {
      ClassLoader cl = Thread.currentThread().getContextClassLoader();
      return ServiceLoader.load(service, cl);
    } 
    
 }

2.LazyIterator源码:
YMeW11.png

  private class LazyIterator implements Iterator<S> {

    Class<S> service;
    ClassLoader loader;
    Enumeration<URL> configs = null;
    Iterator<String> pending = null;
    String nextName = null;

    private LazyIterator(Class<S> service, ClassLoader loader) {
      this.service = service;
      this.loader = loader;
    }

    private boolean hasNextService() {
      if (nextName != null) {
        return true;
      }
      if (configs == null) {
        try {
          Str  
		

请关注公众号获取更多资料


Java编程技术之浅析SPI服务发现机制(一) https://www.cppentry.com/bencandy.php?fid=97&id=287812

首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇【面试题】Java单例设计模式-饿汉.. 下一篇Spring Cloud Alibaba系列(一)n..

评论

验 证 码:
表  情:
内  容: