SPI-Prinzip und tatsächlicher Kampf gegen SPI in Android

1. Hintergrund

Haben Sie irgendwelche Zweifel, bevor Sie die Frage öffnen, das heißt, mit der Entwicklung und dem Wachstum des Unternehmens werden unsere Projektstruktur und unser Codevolumen immer größer und miteinander verflochten, Sie haben mich, ich bin es

Mit Ihnen in der Mitte ist die Arbeitsteilung in der Projektstruktur nicht ganz klar und die Verantwortlichkeiten sind nicht klar. Wenn es online dringende Probleme gibt, die überprüft werden müssen, sind wir möglicherweise in Eile und manchmal nicht klar. Ich weiß nicht, wie ich fragen soll.

Das Problem tritt in diesem Modul auf, was zu einer geringen Effizienz bei der Fehlerbehebung führt und der Projektüberprüfung und Klärung der Verantwortlichkeiten nicht förderlich ist oder wenn der Chef einige Daten wie Geschäftserfolgsrate, Service-Erfolgsrate usw. sehen möchte.

Zu diesem Zeitpunkt können wir es der Einfachheit halber direkt in den Code schreiben. Während das Unternehmen iteriert, kann es sein, dass sich der neue Kollege, der übernimmt, den Kopf zerbricht. Was genau macht dieser Code und warum?

Es sollte hier geschrieben werden (vielleicht hat dieser Code überhaupt keine tatsächliche geschäftliche Bedeutung, es ist nur ein vergrabener Punkt- oder Datenstatistikcode) und andere Probleme, heute werden wir ihn Ihnen großartig vorstellen.

Führen Sie eine neue Lösung ein, um diese Probleme zu lösen. Diese Lösung ist SPI, der vollständige Name ist Service Provider Interface. Natürlich können Sie sagen, dass es auch andere Lösungen gibt, ja, tatsächlich

Es gibt andere Pläne, alle Wege führen nach Rom, OK, reden wir keinen Unsinn und kommen wir zur Sache.

2. Was ist SPI?

SPI (Service Provider Interface) ist eine Reihe von APIs, die vom JDK zur Implementierung oder Erweiterung durch Dritte bereitgestellt werden. Es handelt sich um einen Erkennungsmechanismus für die Dienstregistrierung auf JVM-Ebene.

Kann verwendet werden, um Framework-Erweiterungen und Ersatzkomponenten zu aktivieren, die hauptsächlich von Framework-Entwicklern verwendet werden. Die Hauptidee des SPI-Mechanismus besteht darin, die Steuerung der Baugruppe aus dem Programm zu verlagern.

Dieser Mechanismus ist im Design besonders wichtig und sein Kerngedanke ist die Entkopplung.

2.1: SPI-Gesamtmechanismus

Wie in Abbildung 1 unten dargestellt:

Abbildung 1

Java SPI ist eigentlich ein dynamischer Lademechanismus, der durch die Kombination von „schnittstellenbasierter Programmierung + Strategiemodus + Konfigurationsdatei“ implementiert wird. Die Kernidee ist Dienstregistrierung + Diensterkennung

2.2: Unterschied zwischen SPI und API

Wenn es darum geht, haben viele Leute vielleicht die Frage, was der Unterschied zwischen diesem und API-Aufrufen ist. Okay, um dieses Problem klarer zu erklären, verwenden wir spezielle Diagramme zur Veranschaulichung

SPI与API区别:

API

图2所示

图2

SPI

图3所示

图3

一般模块之间通信基本上都是通过接口,那我们在服务调用方和服务实现方(也称服务提供者)之间引入一个“接口概念”。

当实现方提供了接口和实现,我们可以通过调用实现方的接口从而拥有实现方给我们提供的能力,这就是 API ,这种接口和实现都是放在实现方的。

接口和实现方属于同一个模块,密切不可分割。

当接口存在于调用方这边时,就是 SPI ,由接口调用方确定接口规则,然后由不同的具体业务去根据这个规则对这个接口进行实现,从而提供服务,

举个通俗易懂的例子:一个电脑制造公司,设计好了充电器标准图纸以后,那么接下来就可以把这个图纸分发给不同的厂商去生产,最后只有严格按

照图纸要求,就可以生产合格的商品。

通过上面的图2和图3以及配合上面的文字介绍,相信大家应该很非常清楚API和SPI的区别了.

3.SPI作用

SPI的发现能力是不需要依赖于其他类库,主要实现方式是:

  • java.util.ServiceLoader#load JDK自身提供的加载能力

最重要的作用就是:解耦

4.实现原理

4.1: 源码分析

public final class ServiceLoader<S>

implements Iterable<S>

{

//配置文件所在的包目录路径

private static final String PREFIX = "META-INF/services/";

// 接口名称

private final Class<S> service;

// 类加载器

private final ClassLoader loader;

// The access control context taken when the ServiceLoader is created

// Android-changed: do not use legacy security code.

// private final AccessControlContext acc;

//providers就是不同实现类的缓存,key就是实现类的全限定名,value就是实现类的实例

private LinkedHashMap<String,S> providers = new LinkedHashMap<>();

// //内部类LazyIterator的实例

private LazyIterator lookupIterator;

public void reload() {

providers.clear();

lookupIterator = new LazyIterator(service, loader);

}

private ServiceLoader(Class<S> svc, ClassLoader cl) {

service = Objects.requireNonNull(svc, "Service interface cannot be null");

loader = (cl == null) ? ClassLoader.getSystemClassLoader() : cl;

// Android-changed: Do not use legacy security code.

// On Android, System.getSecurityManager() is always null.

// acc = (System.getSecurityManager() != null) ? AccessController.getContext() : null;

reload();

}

private static void fail(Class<?> service, String msg, Throwable cause)

throws ServiceConfigurationError

{

throw new ServiceConfigurationError(service.getName() + ": " + msg,

cause);

}

Supongo que te gusta

Origin blog.csdn.net/qq_18757557/article/details/128551981
Recomendado
Clasificación