java框架基礎(chǔ)之SPI機(jī)制實(shí)現(xiàn)及源碼解析_第1頁
java框架基礎(chǔ)之SPI機(jī)制實(shí)現(xiàn)及源碼解析_第2頁
java框架基礎(chǔ)之SPI機(jī)制實(shí)現(xiàn)及源碼解析_第3頁
java框架基礎(chǔ)之SPI機(jī)制實(shí)現(xiàn)及源碼解析_第4頁
java框架基礎(chǔ)之SPI機(jī)制實(shí)現(xiàn)及源碼解析_第5頁
已閱讀5頁,還剩2頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第java框架基礎(chǔ)之SPI機(jī)制實(shí)現(xiàn)及源碼解析目錄1定義2案例實(shí)現(xiàn)標(biāo)準(zhǔn)接口廠商的具體接口實(shí)現(xiàn)3SPI機(jī)制源碼分析3.1load加載過程3.2實(shí)例化過程

1定義

SPI的全名為ServiceProviderInterface,用于接口尋找服務(wù)實(shí)現(xiàn)類

實(shí)現(xiàn)方式標(biāo)準(zhǔn)制定者制定接口不同廠商編寫針對(duì)于該接口的實(shí)現(xiàn)類,并在jar的classpath:META-INF/services/全接口名稱文件中指定相應(yīng)的實(shí)現(xiàn)類全類名開發(fā)者直接引入相應(yīng)的jar,就可以實(shí)現(xiàn)為接口自動(dòng)尋找實(shí)現(xiàn)類的功能

2案例實(shí)現(xiàn)

比如我們經(jīng)常看到的緩存類Cache,現(xiàn)在有非常多的緩存框架都會(huì)去實(shí)現(xiàn)這個(gè)接口

標(biāo)準(zhǔn)接口

publicinterfaceCache{

StringgetName();

TTget(Objectkey,ClassTtype);

voidput(Objectkey,Objectvalue);

voidevict(Objectkey);

voidclear();

廠商的具體接口實(shí)現(xiàn)

publicclassConcurrentMapCacheimplementsCache{

privatefinalStringname;

privatefinalConcurrentMapObject,Objectstore;

publicConcurrentMapCache(){

this("defaultMapCache");

publicConcurrentMapCache(Stringname){

this(name,newConcurrentHashMap(256),true);

publicConcurrentMapCache(Stringname,ConcurrentMapObject,Objectstore,booleanallowNullValues){

=name;

this.store=store;

@Override

publicfinalStringgetName(){

return;

@Override

publicTTget(Objectkey,ClassTtype){

Objectvalue=this.store.get(key);

if(value!=nulltype!=null!type.isInstance(value)){

thrownewIllegalStateException("Cachedvalueisnotofrequiredtype["+type.getName()+"]:"+value);

return(T)value;

@Override

publicvoidput(Objectkey,Objectvalue){

this.store.putIfAbsent(key,value);

@Override

publicvoidevict(Objectkey){

this.store.remove(key);

@Override

publicvoidclear(){

this.store.clear();

注意:一定要有默認(rèn)無參構(gòu)造器,否則之后無法通過SPI機(jī)制實(shí)例化對(duì)象

配置地址

在resouce下的META-INF\services文件下的spi.Cache文件內(nèi)容是服務(wù)類的全限命名:spi.ConcurrentMapCache

打包jar并引入到項(xiàng)目

測(cè)試

publicclassCacheSpiTest{

publicstaticvoidmain(String[]args){

ServiceLoaderCacheserviceLoader=ServiceLoader.load(Cache.class);

IteratorCacheiterator=serviceLoader.iterator();

while(iterator.hasNext()){

Cachecache=iterator.next();

System.out.println(cache.getName());

cache.put("user","nana");

System.out.println(cache.get("user",String.class));

打印結(jié)果:

defaultMapCache

nana

說明獲取到了定制接口的實(shí)現(xiàn)類對(duì)象

通過上述例子,我們知道ServiceLoader是用于通過接口獲取接口實(shí)現(xiàn)類的工具

3SPI機(jī)制源碼分析

3.1load加載過程

ServiceLoader成員變量

//SPI約定獲取擴(kuò)展接口路徑的文件

privatestaticfinalStringPREFIX="META-INF/services/";

//基礎(chǔ)約定接口

privatefinalClassSservice;

privatefinalClassLoaderloader;

//權(quán)限控制上下文

privatefinalAccessControlContextacc;

//廠商接口實(shí)現(xiàn)類的實(shí)例化對(duì)象集合

privateLinkedHashMapString,Sproviders=newLinkedHashMap();//以初始化的順序緩存接口全名稱,實(shí)現(xiàn)類實(shí)例

//懶加載迭代器

privateLazyIteratorlookupIterator

load()初始化

publicvoidreload(){

providers.clear();

lookupIterator=newLazyIterator(service,loader);

privateServiceLoader(ClassSsvc,ClassLoadercl){

service=Objects.requireNonNull(svc,"Serviceinterfacecannotbenull");

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

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

reload();

load()方法并沒有實(shí)例化具體實(shí)現(xiàn)類,而是加載需要實(shí)例化的對(duì)象路徑

3.2實(shí)例化過程

ClassSservice;//通用接口

ClassLoaderloader;//類加載器

EnumerationURLconfigs=null;//廠商接口文件URL的集合

IteratorStringpending=null;//接口具體實(shí)現(xiàn)的路徑類名列表

publicbooleanhasNext(){

if(acc==null){//訪問控制上下文是否為空

returnhasNextService();

}else{

PrivilegedActionBooleanaction=newPrivilegedActionBoolean(){

publicBooleanrun(){returnhasNextService();}

returnAccessController.doPrivileged(action,acc);

publicSnext(){

if(acc==null){

returnnextService();

}else{

PrivilegedActionSaction=newPrivilegedActionS(){

publicSrun(){returnnextService();}

returnAccessController.doPrivileged(action,acc);

hasNext():先從provider中查找,如果有,返回true;如果沒有,通過LazyIterator來進(jìn)行查找.在hasNext()方法中會(huì)獲取當(dāng)前需要實(shí)例化的類名nextName,然后在next()方法中具體實(shí)例化

next():先從provider中直接獲取,如果有,返回實(shí)現(xiàn)類對(duì)象實(shí)例;如果沒有,通過LazyIterator中nextService()來進(jìn)行獲取

privateSnextService(){

if(!hasNextService())//獲取nextName需要加載的類名

thrownewNoSuchElementException();

Stringcn=nextName;

nextName=null;

Classc=null;

try{

c=Class.forName(cn,false,loader);

}catch(ClassNotFoundExceptionx){

fail(service,

"Provider"+cn+"notfound");

if(!service.isAssignableFrom(c)){

fail(service,

"Provider"+cn+"notasubtype");

try{

Sp=service.cast(c.newInstance());//初始化類并類型轉(zhuǎn)換成Cache對(duì)象

providers.put(cn,p);放入實(shí)例化對(duì)象集合中

returnp;

}catch

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論