日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

自定义ServicesLoader来实现根据配置使用不通的SPI实现从而实现项目扩展

發(fā)布時間:2025/5/22 编程问答 56 豆豆
生活随笔 收集整理的這篇文章主要介紹了 自定义ServicesLoader来实现根据配置使用不通的SPI实现从而实现项目扩展 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>

自定義ServicesLoader來實(shí)現(xiàn)根據(jù)配置使用不通的SPI實(shí)現(xiàn)從而實(shí)現(xiàn)項目擴(kuò)展

?

一 、 ?都知道Java中的SPI技術(shù),也是dubbo中實(shí)驗(yàn)的,

通過這個案例可以快速的了解spi是什么?https://my.oschina.net/lenglingx/blog/879292

這個案例就是直接簡單使用的spi,都說dubbo是也是使用spi來做擴(kuò)展的,去看了一下dubbo的介紹,了解到了:ExtensionLoader.java

且dubbo使用是通過配置來的,如注冊協(xié)議有,redis,和zookeeper。

這里我們就介紹如何實(shí)現(xiàn)通過配置來和spi結(jié)合實(shí)現(xiàn)dubbo這樣的。

?

二、 ?這個項目介紹,log-parent,為整體項目,內(nèi)部有4個項目。

log為api的接口項目

alog為ALog實(shí)現(xiàn)

blog為BLog實(shí)現(xiàn)

logTest為這個 log的測試項目

log項目的Log接口

package com.tspi.log;public interface Logger {public void debug(String logger);public void info(String logger);public void warn(String logger);public void error(String logger);}

CustomServiceLoader自定義serviceLoader

package com.tspi.log;import java.net.URL; import java.util.Enumeration; import java.util.HashMap; import java.util.Map;import org.apache.commons.io.IOUtils;public class CustomServiceLoader {public static final String MAPPING_CONFIG_PREFIX = "META-INF/services";public static Map mservices;public static <S> Map<String, Class<S>> loade(Class<S> service) throws Exception {String mappingConfigFile = MAPPING_CONFIG_PREFIX + "/log/" + service.getName();// 由于一個接口的實(shí)現(xiàn)類可能存在多個jar包中的META-INF目錄下,所以下面使用getResources返回一個URL數(shù)組System.out.println("configFile:" + mappingConfigFile);Enumeration<URL> configFileUrls = CustomServiceLoader.class.getClassLoader().getResources(mappingConfigFile);if (configFileUrls == null) {return null;}//List<S> services = new LinkedList<S>();mservices = new HashMap<String, Class<S>>();while (configFileUrls.hasMoreElements()) {URL configFileUrl = configFileUrls.nextElement();String configContent = IOUtils.toString(configFileUrl.openStream());System.out.println("configContent:");System.out.println(configContent);System.out.println("configContent --end");String[] serviceNames = configContent.split("\n");for (String serviceName : serviceNames) {System.out.println("serviceName: " + serviceName);String[] tempServiceName = serviceName.split("=");System.out.println("tmpServiceName:" + tempServiceName[0] + "," +tempServiceName[1]);ClassLoader classLoader = CustomServiceLoader.class.getClassLoader();System.out.println("classloader:" + classLoader);Class class1 = classLoader.loadClass(tempServiceName[1]);System.out.println("class1" + class1);Object serviceInstance = class1.newInstance();Logger log = (Logger)serviceInstance;log.warn("TEST!!!");//services.add((S) serviceInstance);mservices.put(tempServiceName[0], serviceInstance);}}System.out.println("-----");System.out.println("mservices:" + mservices.toString());return mservices;}public static Object getType(String type) {System.out.println("type:" + type);System.out.println("-----");System.out.println("mservices:" + mservices.toString());return mservices.get(type);}}

?

alog項目:

ALogger實(shí)現(xiàn):

package com.tspi.alog;import com.tspi.log.Logger;public class ALogger implements Logger{public ALogger() {}public void debug(String logger) {System.out.println("ALogger-->debug: " + logger);}public void info(String logger) {System.out.println("ALogger-->info: " + logger); }public void warn(String logger) {System.out.println("ALogger-->warn: " + logger);}public void error(String logger) {System.out.println("ALogger-->error: " + logger);}}

同時在resources目錄下添加

META-INF/services/log/com.tspi.log.Logger ?這個文件。

內(nèi)容為

alog=com.tspi.alog.ALogger

?

blog項目同alog 項目已樣:

package com.tspi.blog;import com.tspi.log.Logger;public class BLogger implements Logger{public BLogger() {}public void debug(String logger) {System.out.println("BLogger-->debug: " + logger);}public void info(String logger) {System.out.println("BLogger-->info: " + logger); }public void warn(String logger) {System.out.println("BLogger-->warn: " + logger);}public void error(String logger) {System.out.println("BLogger-->error: " + logger);} }

同樣在resources目錄下添加

META-INF/services/log/com.tspi.log.Logger ?這個文件。

內(nèi)容為

blog=com.tspi.blog.BLogger

?

logTest項目:

App.java

package com.tspi.logtest;import java.util.ResourceBundle;import com.tspi.log.CustomServiceLoader; import com.tspi.log.Logger;/*** Hello world!**/ public class App {public static void main(String[] args) {System.out.println("Hello World!");ResourceBundle log = ResourceBundle.getBundle("log");String logString = log.getString("logType");System.out.println("logType:" + logString);CustomServiceLoader customServiceLoader = new CustomServiceLoader();try {customServiceLoader.loade(Logger.class);} catch (Exception e) {e.printStackTrace();}System.out.println("logString:" + logString);Logger logger = (Logger) customServiceLoader.getType(logString);logger.info("我愛你。。。");} }

這個項目依賴著前面三個項目,在這個項目的resources這個目錄下新建log.properties文件,內(nèi)容如下:

logType=blog

可以是alog或者blog。配置不同,將調(diào)用不同的實(shí)現(xiàn)。

運(yùn)行如下:

Hello World! logType:blog configFile:META-INF/services/log/com.tspi.log.Logger configContent: alog=com.tspi.alog.ALogger configContent --end serviceName: alog=com.tspi.alog.ALogger tmpServiceName:alog,com.tspi.alog.ALogger classloader:sun.misc.Launcher$AppClassLoader@73d16e93 class1class com.tspi.alog.ALogger ALogger-->warn: TEST!!! configContent: blog=com.tspi.blog.BLogger configContent --end serviceName: blog=com.tspi.blog.BLogger tmpServiceName:blog,com.tspi.blog.BLogger classloader:sun.misc.Launcher$AppClassLoader@73d16e93 class1class com.tspi.blog.BLogger BLogger-->warn: TEST!!! ----- mservices:{blog=com.tspi.blog.BLogger@14ae5a5, alog=com.tspi.alog.ALogger@7f31245a} logString:blog type:blog ----- mservices:{blog=com.tspi.blog.BLogger@14ae5a5, alog=com.tspi.alog.ALogger@7f31245a} BLogger-->info: 我愛你。。。

?

如果配置的是alog,

最后打印將會是ALogger-->info: 我愛你。。。

?

三、 ?后記

這基本就是一個很簡單的自定義servicesLoader的實(shí)現(xiàn)。基本實(shí)現(xiàn)了讀配置來覺得調(diào)不通的SPI的實(shí)現(xiàn)

就像使用dubbo注冊時你配置的是的redis就使用了redis注冊中心,zookeeper就使用了zookeeper注冊中心,我們這是配置alog就使用了ALogger實(shí)現(xiàn),配置blog就使用了BLogger實(shí)現(xiàn)一樣。

這個例子的地址:https://git.oschina.net/lenglingx-163/log-parent.git

?

?

?

轉(zhuǎn)載于:https://my.oschina.net/lenglingx/blog/1505958

總結(jié)

以上是生活随笔為你收集整理的自定义ServicesLoader来实现根据配置使用不通的SPI实现从而实现项目扩展的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。