Dubbo解析(一)-內核實現之SPI機制(上)

Dubbo採用微內核+插件的方式,使得設計優雅,擴展性強。但也給源碼的學習帶來了必定的困難,初看者經常迷失在找不到方法的具體實現。在學習dubbo源碼前,必需要了解其內核的SPI機制.什麼是SPI,它是JDK內置的一種服務發現機制,全稱是Service Provider Interface(服務提供者接口),也就是尋找接口服務的提供者的一種規範。java

舉個例子,你在淘寶上賣東西,客戶下單後要發快遞,通常你會找快遞公司幫你運輸。快遞公司有不少家,不一樣的快遞公司提供的服務也不一樣,好比順豐可能就快一點,韻達可能就慢一點。發快遞就是一個接口服務,而真正的實現由不一樣的快遞公司來完成。ide

定義一個發快遞的接口學習

package com.lntea.dubbo.demo.spi;
public interface Delivery {

	void deliveryProduct(String productName);
}

有兩個不一樣的實現編碼

// 順豐
package com.lntea.dubbo.demo.spi;
public class ShunFengDelivery implements Delivery{

	public void deliveryProduct(String productName) {
		System.out.println("你的" + productName + "到家了,順豐快遞爲您服務");
	}

}

// 韻達
package com.lntea.dubbo.demo.spi;
public class YunDaDelivery implements Delivery{

	public void deliveryProduct(String productName) {
		System.out.println("你的" + productName + "到家了,韻達快遞爲您服務");
	}

}

由於快遞公司是第三方,咱們定義快遞接口服務時,根本不知道發快遞的究竟是哪家公司。JDK的SPI機制就定義了一些規範,來幫助咱們尋找服務的提供者實現:spa

  1. 在classpath的META-INF/services/目錄下建立名稱爲服務接口的全限定名(package+className)的文件,文件編碼必須爲UTF-8,文件內容爲服務接口實現類的全限定名,一個文件內能夠定義多個實現類,按行分開便可。
  2. 服務接口實現類必須有一個無參的構造方法。
  3. 使用java.util包下的ServiceLoader類的load方法動態加載接口的實現類。

按照JDK的SPI機制完成發快遞的代碼插件

package com.lntea.dubbo.demo.spi;

import java.util.Iterator;
import java.util.ServiceLoader;

import org.junit.Test;

public class DeliveryTest {
	
	@Test
	public void testDeliveryProduct(){
		String productName = "Iphone X";
		delivery(productName);
	}

	private void delivery(String productName) {
		ServiceLoader<Delivery> loader = ServiceLoader.load(Delivery.class);
		Iterator<Delivery> iterator = loader.iterator();
		while(iterator.hasNext()){
			Delivery delivery = iterator.next();
			delivery.deliveryProduct(productName);
		}
	}
}
輸入結果以下:
你的Iphone X到家了,順豐快遞爲您服務
你的Iphone X到家了,韻達快遞爲您服務

ServiceLoader實現了Iterable接口,能夠遍歷每個服務提供者,並調用它的服務。結果就是客戶買了一個Iphone X, 結果你快遞了兩個給人。固然淘寶賣家不會這麼傻,通常都會默認一家快遞公司,或者客戶能夠指定其餘的快遞公司,咱們就須要接口中定義一個匹配方法。設計

public interface Delivery {

    // 公司名稱是否匹配
	boolean match(String companyName);
	void deliveryProduct(String productName);
}

那順豐和韻達在服務實現類中就要匹配本身的公司名稱code

// 順豐
public class ShunFengDelivery implements Delivery{

	public boolean match(String companyName) {
		return "sf".equals(companyName);
	}
	
	public void deliveryProduct(String productName) {
		System.out.println("你的" + productName + "到家了,順豐快遞爲您服務");
	}

}

// 韻達
public class YunDaDelivery implements Delivery{

	public boolean match(String companyName) {
		return "yd".equals(companyName);
	}
	
	public void deliveryProduct(String productName) {
		System.out.println("你的" + productName + "到家了,韻達快遞爲您服務");
	}

}

發快遞的代碼也須要變動接口

public class DeliveryTest {
	
	@Test
	public void testDeliveryProduct(){
		String productName = "Iphone X";
		String companyName = "sf";
		delivery(companyName, productName);
	}

	private void delivery(String companyName, String productName) {
		ServiceLoader<Delivery> loader = ServiceLoader.load(Delivery.class);
		Iterator<Delivery> iterator = loader.iterator();
		while(iterator.hasNext()){
			Delivery delivery = iterator.next();
			// 匹配指定的快遞公司
			if(delivery.match(companyName)){
				delivery.deliveryProduct(productName);
				break;
			}
		}
	}
}

輸出結果:
你的Iphone X到家了,順豐快遞爲您服務

以上介紹了JDK的SPI機制,而Dubbo內核對於擴展點的加載方式就是從JDK的SPI機制加強而來的。那麼JDK的SPI機制有什麼缺點呢,Dubbo的SPI機制又增長了哪些呢,下一章見。源碼

相關文章
相關標籤/搜索