OSGIおよびJigsawを使用しないJavaSEでのモジュール化

mvn-classloader -Maven互換リポジトリのクラスとリソースのローダー。 このプロジェクトを使用すると、OSGIのすべての能力と複雑さを必要としないJavaSEアプリケーションに、複雑なモジュールシステムではなく、限られたスコープを追加できます。









この記事では、モジュール以外にmvn-classloaderでできることについて学習します。



dzone ModRunに関する一般的な記事の1つ、 JigsawのないModularity-Jigsawなしで読んだときに、非常に明白なことについて書くというアイデアが生まれました。 人々がソリューションを探す方法を知らない場合、機能が「不足」する別の自転車を作成し、以前に実装されたものやgithubおよび中央のMavenリポジトリにあるものを見ない場合は悲しいです。



mvn-classloaderが役立つのは何ですか





プロキシリポジトリの背後にある隔離されたネットワークを持つ血まみれの企業で働くことについてのいくつかの言葉。ここでもmavenが事実上の標準です。 このプロジェクトの設定は、デフォルトで〜/ .m2 / settings.xmlおよび〜/ .m2 / settings-security.xmlからmavenを読み取ります。 また、Mavenが正しく構成されていて、すべてが機能する場合、追加の構成は必要ありません。

システムプロパティを使用してこれらの設定をオーバーライドできます(仮想マシンの起動時に「-D」でパラメーターとして渡されます)。





このプロジェクトは、中央のMavenリポジトリcom.github.igor-suhorukov:mvn-classloader:1.8およびgithubで入手できます。



順番に、利用可能な機能と使用例を検討します。



Mavenからクラスをロードする



ブートローダーを作成するためのエントリポイントは、クラスcom.github.igorsuhorukov.smreed.dropship.MavenClassLoaderです。



最も簡単な開始方法は、forMavenCoordinates(...)メソッドを使用することです。これは、settings.xmlファイルのmirror-ofセクションで指定された中央のMavenリポジトリまたはそのミラーからクラスをロードします。



参照によって別のリポジトリからクラスをロードする場合は、usingメソッド(link_to_ma__repository).forMavenCoordinates(...)を呼び出す必要があります。



クラスローダーのMavenのアーティファクトの座標は、groupId:artifactId [:extension [:classifier]]:versionの形式です。



io.hawtアーティファクトからio.hawt.app.Appクラスを読み込む例から始めましょう:hawtio-app:2.0.0。 独自のバージョンのjetty Webサーバーとロガークラスがある分離クラスローダーを作成しましょう。 これは、アプリケーションと同じjvmプロセスで管理コンソールを起動するために必要です。



Javaでクラスを操作する場合、リフレクションを使用する必要があります。



Class<?> hawtIoConsole = MavenClassLoader.usingCentralRepo().forMavenCoordinates("io.hawt:hawtio-app:2.0.0").loadClass("io.hawt.app.App"); Thread.currentThread().setContextClassLoader(hawtIoConsole.getClassLoader()); Method main = hawtIoConsole.getMethod("main", String[].class); main.invoke(null, (Object) new String[]{"--port","10090"});
      
      





Groovyでは、同じコードがより簡潔に記述されています。



 def hawtIoConsole = MavenClassLoader.usingCentralRepo().forMavenCoordinates('io.hawt:hawtio-app:2.0.0').loadClass('io.hawt.app.App') Thread.currentThread().setContextClassLoader(hawtIoConsole.getClassLoader()) hawtIoConsole.main('--port','10090')
      
      





アプリケーションモジュールが相互にやり取りする必要がある場合は、ローダー、階層、およびおそらくMavenServiceLoaderのいくつかがなくてはできません。OSGIサービスの基本的な代替手段として役立ちます。 複数のクラスローダーの使用の概要については、「クラスローダーの階層の作成」を参照してください。



MavenServiceLoader



このサービスローダーは、java.util.ServiceLoaderを使用してMavenモジュールからクラスをロードします。 ただし、アーティファクトがサービスを提供するには、サービス記述子をMETA-INF / servicesアーティファクトにパックする必要があります。 ServiceLoaderがjavadocでどのように機能するかについて詳しく読むか、 camel-url-handlerおよびvfs-url-handlerプロジェクトのサービスの例を使用してServiceLoaderがどのように実装されるかを確認できます。



例として、プロトコル変数で渡すもの-vfsまたはcamel-URLStreamHandlerFactoryサービスの実装は、対応するアーティファクトvfs-url-handlerまたはcamel-url-handlerからロードされます。



 String artifact = System.getProperty(protocol+"MvnUrlHandler", String.format("com.github.igor-suhorukov:%s-url-handler:LATEST",protocol)); Collection<URLStreamHandlerFactory> urlStreamHandlerFactories = MavenServiceLoader.loadServices(artifact, URLStreamHandlerFactory.class);
      
      





リポジトリからバイナリとリソースをダウンロードする



プロジェクトを使用して、分類子を指定し、アーティファクト座標を入力するだけで、Mavenリポジトリからバイナリアーティファクトをロードできます。 例として、Chrome用のWebドライバーをダウンロードして起動します。 実際のブラウザー用のWebドライバーには、クライアント側APIに加えて、ブラウザーをアプリケーションのパペットにする別のプロセスで実行可能な部分があります。 多くの場合、手動でダウンロードされ、アプリケーションのパスを示します。 しかし、なぜ、あなたがそれを自動的にできるのか!?



どのオペレーティングシステムに応じて、os win32、linux64またはmac64を値として渡す必要があります。 Win32は64ビットシステムでも動作します。



 String chromedriver = MavenClassLoader.usingCentralRepo().resolveArtifact("com.github.igor-suhorukov:chromedriver:bin:" + os + ":2.24").getFile(); //   linux     chmod(chromedriver); System.setProperty("webdriver.chrome.driver", chromedriver);
      
      





クラスローダー階層を作成する



クラスcom.github.igorsuhorukov.smreed.dropship.MavenClassLoaderへのメソッド呼び出しを使用して、Mavenからのクラスローダーの作成を組み合わせる





そして、これらのさまざまなブートローダーから、新しい集約された「ルート」ブートローダーを作成します。 これを行うには、ClassLoader配列からクラスローダーを使用できます。



 com.github.igorsuhorukov.codehaus.spice.classman.runtime.JoinClassLoader(ClassLoader[] classLoaders, ClassLoader parent)
      
      





このアプローチを使用しすぎると、しばらくすると、クラスをロードする複雑さでアプリケーションがOSGI / JEEサーバーを上回ります。 これに関与してクラスローダーの階層で混乱するかどうかは、スペシャリストとしてのあなた次第です。 問題を解決するためにこのようなツールが必要な場合は、利用できます。 複雑なケースや、複雑な初期化順序を持つ多数の依存モジュールでは、動的なクラスの再読み込みが必要な場合と同様に、OSGIが最適なソリューションになります。



Mavenリポジトリからアプリケーションをダウンロードして起動します



mvn-classloaderは、Mavenアーティファクトからクラスをロードして実行できます。 これは簡単です。コマンドラインでgroupId:artifactId [:version] classnameパラメーターを渡すだけです。 例を挙げます。



1つのコマンドでhttpプロキシを起動します



 java -Dos.detected.classifier=windows-x86_64 -jar mvn-classloader-1.8.jar org.littleshoot:littleproxy:1.1.0 org.littleshoot.proxy.Launcher
      
      





または、git gitblitサーバーを起動します。



 java -jar mvn-classloader-1.8.jar org.eclipse.jetty:jetty-runner:9.4.0.v20161208 org.eclipse.jetty.runner.Runner http://gitblit.github.io/gitblit-maven/com/gitblit/gitblit/1.8.0/gitblit-1.8.0.war
      
      





UniversalURLStreamHandlerFactory



UniversalURLStreamHandlerFactoryは、ロード可能なプロトコル実装用のURLハンドラーであり、mvn-classloaderで使用可能です。 それらをMavenリポジトリからロードするか、ローカルリポジトリキャッシュを使用します。



次のプロトコルがURLでサポートされるようになりました。





Javaプログラムにユニバーサルハンドラーを登録するのは簡単です。URLでこのようなエキゾチックなアドレスを使用する前に初期化を追加するだけです。



 java.net.URL.setURLStreamHandlerFactory(new com.github.igorsuhorukov.url.handler.UniversalURLStreamHandlerFactory());
      
      





ただし、java.net.URL.setURLStreamHandlerFactoryをプログラム全体で1回しか呼び出せないという、標準のJavaライブラリの制限を覚えておく必要があります。



java.net.URLの記事でその使用例を見つけることができます。 そうしないと、古い馬は溝を損ないません



Grovey Grape Movement



mvn-classloaderには、スプリングブートプロジェクトのAetherGrapeEngineと、動作するために最低限必要な依存関係も含まれています。



GrapeはGroovyに組み込まれている依存関係解決エンジンですが、すぐに使えるIvy実装はありません。 スクリプトのストリートマジックはこれについて語っていますそれともGroovy、Ivy、Mavenをつなぐものですか? 。 そして、グルーヴィーなハブの私のほぼすべての記事で、例を挙げます。 単一のgroovyファイルの形式でビデオ登録された冷蔵庫のアラームシステムの最新の例:



java -Dlogin = ... YOUR_EMAIL ... @ mail.ru -Dpassword = ******* -jar groovy-grape-aether-2.4.5.4.jar AlarmSystem.groovy



おわりに



数年前、私は1つのプロジェクトでいくつかのオープンソース技術を見つけ、統合し、完成させました。 作業に必要なすべての依存関係は、1つのmvn-classloader.jarファイルにまとめられています。 すべてのテクノロジーと同様に、mvn-classloaderには独自の適用分野があります。OSGIでは下位レベルのクラスでも動作しないため、ダイナミズムとクラスのリロードはありません。 ただし、リストされたタスクの場合、JEEを使用しないマイクロサービスアーキテクチャを備えたプロジェクトを含め、mvn-classloaderが最適な選択肢です。 彼の主な仕事では、彼は積極的にそれを使用して、 aspectj-scriptingの一部として複雑な分散システムを変更およびテストしました。



この記事に記載されている機能のいずれかが必要な場合は、Mavenアセンブリに依存関係を追加するだけです。



 <dependency> <groupId>com.github.igor-suhorukov</groupId> <artifactId>mvn-classloader</artifactId> <version>1.8</version> </dependency>
      
      





またはグラドル



 compile group: 'com.github.igor-suhorukov', name: 'mvn-classloader', version: '1.8'
      
      





プロジェクトで使用を開始してください!










All Articles