SPI の正式名は Service Provider Interface で、フレームワークの拡張機能やコンポーネントの置き換えを開始するために使用できます。
本質は、インターフェイス実装戦略モード構成ファイルを使用して実装クラスを動的にロードすることです。
具体的な使用方法では、いくつかの規則があります。
(1) インターフェースのフルネームファイルは、classPath
# の META-INF/services/ 配下に作成されると規定されています。 ## (2) このファイルには、インタフェース実装クラスのフルネーム(パスファイル名)を記述します(実装クラスが複数ある場合は、行を分けて記述します)。 (3) 2を利用する場合は、java.util.ServiceLoaderのload(Interface.class)で実装クラスを取得することで利用可能になります。 インターフェイス実装クラスにはパラメーターのないコンストラクターが必要であることに注意してください。 実装ケースこのアプリケーションでは、A モジュールと B モジュールの 2 つのモジュールがあり、この 2 つのモジュールのうち、A モジュールがメイン モジュール、B がスレーブ モジュール、B モジュールが存在します。モジュールはモジュール A に依存します。しかし現在、モジュール B に実装されているクラスが存在します。モジュール A はこのクラスの関数を呼び出す必要があり、モジュールはモジュール B に依存できなくなります。この時点で、デカップリングが必要です。この実装では、デカップリング実装に SPI が使用されます。具体的な実装計画は次のとおりです: (1) モジュール A に新しいインターフェイスを作成します: MyLogAppender. 具体的な実装は次のとおりです:/** * @author Huang gen(kenfeng) * @description 自定义的appender接口 * @Since 2021/02/21 **/ public interface MyLogAppender { /** * 获取实现的appender * @return 返回新建的appender对象 * */ Appender getAppender(); }
/** * @author Huang gen(kenfeng) * @description 自定义的appender * @Since 2021/02/21 **/ @Component public class MeshLogAppender extends UnsynchronizedAppenderBase<ILoggingEvent> implements MyLogAppender,ApplicationContextAware { private ApplicationContext applicationContext; public MeshLogAppender(){ } @Override public Appender getAppender() { MeshLogAppender meshLogAppender = new MeshLogAppender(); return meshLogAppender; } @Override protected void append(ILoggingEvent iLoggingEvent) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String std = simpleDateFormat.format(new Date(Long.parseLong(String.valueOf(iLoggingEvent.getTimeStamp())))); String log = std + "\t" + iLoggingEvent.getLevel() +"\t"+"--- ["+ iLoggingEvent.getThreadName()+"]\t"+iLoggingEvent.getCallerData()[0]+":\t "+iLoggingEvent.getMessage(); FlowMessage input = new FlowMessage(); MeshFlowService meshFlowService = SandboxSystemServiceFactory.getService(MeshFlowService.class); Map<String, Object> body = new HashMap<>(2); body.put("log",log); input.setTenantCode(DefaultTenant.get()); input.setAppCode("epoch"); input.setFlowCode("log_broadcast"); input.setBody(body); FlowMessage output = meshFlowService.process(input); if(!StringUtils.isEmpty(output.getErrorMessage())){ throw new RuntimeException("发布日志时,广播失败"); } } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } }
ServiceLoader<MyLogAppender> myLoaderInterfaceServiceLoader = ServiceLoader.load(MyLogAppender.class); Iterator<MyLogAppender> myLoaderInterfaceIterator = myLoaderInterfaceServiceLoader.iterator(); while (myLoaderInterfaceIterator.hasNext()){ MyLogAppender myLoaderInterface = myLoaderInterfaceIterator.next(); Appender newAppender = myLoaderInterface.getAppender(); newAppender.setName("application"); newAppender.setContext(loggerContext); newAppender.start(); rootLogger.addAppender(newAppender); }
以上がSPI を使用して Java でデカップリングを実現する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。