Spring BootをOSGiで使用できますか?そうでない場合、OSGi Spring Boot(Apache FelixまたはEclipse Equinox)を計画していますか?私の意見では、クラウドアプリケーションはOSGiが提供するように高度にモジュール化され、更新可能でなければなりません。
はい、OSGIコンテナで_Spring Boot
_アプリを実行することは可能です。
まず、Spring Boot jar
パッケージからOSGI bundle
に切り替える必要があります。
Maven
を使用している場合は、_org.Apache.felix:maven-bundle-plugin
_を使用できます。 _Spring Boot
_依存関係jarは有効なOSGI
バンドルではないため、bnd
ツールを使用して有効なバンドルにするか、バンドル自体に埋め込むことができます。これは、_maven-bundle-plugin
_構成、特に_<Embed-Dependency>
_を使用して行うことができます。
ただし、どうにかして_Spring Boot
_アプリでバンドルを開始する必要があります。アイデアは、BundleActivator
でSpring Bootを開始することです。
_@Import(AppConfig.class)
@SpringBootConfiguration
@EnableAutoConfiguration
public class SpringBootBundleActivator implements BundleActivator {
ConfigurableApplicationContext appContext;
@Override
public void start(BundleContext bundleContext) {
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
appContext = SpringApplication.run(SpringBootBundleActivator.class);
}
@Override
public void stop(BundleContext bundleContext) {
SpringApplication.exit(appContext, () -> 0);
}
}
_
また、Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
によってバンドルをロードするOSGIクラスローダーにコンテキストクラスローダーを設定する必要があります。 Spring
はコンテキストクラスローダーを使用するため、これが必要です。
これは私のデモリポジトリで実際に見ることができます: https://github.com/StasKolodyuk/osgi-spring-boot-demo
個別の回答として投稿する価値があると思います(回答に対するすべてのコメントを全員が読むわけではありません)。
@StasKolodyukの優れたソリューションは、OSGI環境でSpring Bootアプリケーションを実行する方法を提供します。
ただし、制限があります。OSGIで実行するとパッケージスキャンがサポートされないため、Spring Bootのアノテーションによる自動マッピングは機能しません。
これが別のトリックです。コンポーネントを備えたSpring Bootアプリをコードから自動取得してOSGIで実行することができます(私はKarafでテストしました)。
機能例は https://github.com/dimmik/osgi-spring-boot-demo にあります
コツは、SpringApplicationインスタンスに適切なResourcePatternResolverを提供することです。
package by.kolodyuk.osgi.springboot;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.osgi.io.OsgiBundleResourcePatternResolver;
@SpringBootApplication
public class SpringBootBundleActivator implements BundleActivator {
ConfigurableApplicationContext appContext;
@Override
public void start(BundleContext bundleContext) {
// Set context classloader (main trick, to enable SpringBoot start at the first place)
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
// trick to enable scan: get osgi resource pattern resolver
OsgiBundleResourcePatternResolver resourceResolver = new OsgiBundleResourcePatternResolver(bundleContext.getBundle());
// and provide it to spring application
appContext = new SpringApplication(resourceResolver, SpringBootBundleActivator.class).run();
}
@Override
public void stop(BundleContext bundleContext) {
SpringApplication.exit(appContext, () -> 0);
}
public static void main(String[] args) {
SpringApplication.run(SpringBootBundleActivator.class);
}
}
1つの可能性は、OSGiをSpring Bootアプリケーションに組み込んで、フレームワークを通じてアプリケーションの一部にアクセスできるようにすることです。 OSGiをプログラムで開始する方法については、 https://stackoverflow.com/a/4673904/173101 を参照してください。
しかし、一般的には「OSGi-Support」のようなものはありません。 OSGiはすべてのJavaアプリケーションに統合できます。逆の場合も同様に、すべてのJavaコード(また、Spring-Bootアプリケーション)をOSGiバンドルにパッケージ化して、OSGiコンテナー内で起動できます(ただし、それほど多くはありません)まったく意味がありません)。
Spring BootをOSGiにデプロイする理由はたくさんありますが、主な理由はパフォーマンスです。特に、Spring Bootサービスが機能しているサービス(つまり、開始、結果を返す、終了)の場合の起動パフォーマンスです。 Spring Bootで現在ベータテスト中のアプリケーションは、Equinoxにデプロイされた約0.5秒で起動するのに対し、3.5秒で起動します。他の理由は、OSGiベースのアプリケーションまたはJava EEサーバーへの統合です。
つまり、パフォーマンス上の理由から、OSGiはOSGi実装としてFelixまたはEquinoxよりもOSGi実装として多分優先されるでしょう。
別の代替方法は、Spring Bootアプリケーションで使用されるSpringライブラリを(WSO2から)MSF4Jにラップすることです。これは多くの作業を必要とせず、メモリ使用量の1/10で10倍高速に起動できます。
スプリングブート-典型的なスプリングブートアプリは、osgiにとって少し「脂肪」です... starter-webまたはjerseyを使用している場合、ポートはすべてのosgiによって共有されるため、何らかのポート決定スキームを追加する必要があります。サービス」は、osgiランタイムが存在するシステムです。
私がスプリングブートを回避することができない限り、それを回避できないことをお勧めする理由は、作成したスプリングブートファットjar/warがサブクラスローダーを起動するためです。これは、標準のosgiクラスローダーの問題(com.whatever.someobject.MyClassが異なるバンドルとクラスローダーで同じではないため、他のすべてにエクスポートする同じバンドルから「インポート」されないため、混乱する場合)を単純化しません。バンドル間サービス通信の要件がある場合。
Webリスナーを必要としない場合は「スプリングブートコア」に対処するためのガイドに従い、標準のインポートに含まれないオブジェクトを使用するすべてのバンドル間サービスインターフェース(core =など)を回避することをお勧めしますJava se class etc ..)。ライフサイクルのみに関心がありますか?
いいえ、OSGiをサポートしていません。 Spring Bootは、すべての依存関係を持つパッケージ化されたアプリケーションとしてマイクロサービスを作成し、実行可能JARにパッケージ化されたサーブレットコンテナーを作成することを目的としています。
マイクロサービスパターンに固執せず、OSGIアプリをREST API。簡単に管理するREST通信