コンテンツ
1.SpringBootApplicationの背後にある秘密
自動構成の背後にあるヒーロー:SpringFactoriesLoaderの詳細
次に、SpringApplication実行プロセスの詳細な調査
Spring Bootプロジェクトを開発するときは、次のスタートアップクラスを使用します
1 @SpringBootApplication 2 public class Application { 3 public static void main(String [] args){ 4 SpringApplication.run(Application.class、args); 5} 6}
上記のコードからわかるように、アノテーション定義(@SpringBootApplication)とクラス定義(SpringApplication.run)が最も魅力的であるため、SpringBootの謎を解明するには、これら2つから始める必要があります。
1.SpringBootApplicationの背後にある秘密
@SpringBootApplicationアノテーションは、Spring Bootのコアアノテーションであり、実際には結合されたアノテーションです。
1 @Target(ElementType.TYPE) 2 @Retention(RetentionPolicy.RUNTIME) 3 @Documented 4 @Attached 5 @SpringBootConfiguration 6 @EnableAutoConfiguration 7 @ComponentScan(excludeFilters = { 8 @Filter(type = FilterType.CUSTOM、classes = TypeExcludeFilter.class )、 9 @Filter(type = FilterType.CUSTOM、classes = AutoConfigurationExcludeFilter.class)}) 10 public @interface SpringBootApplication { 11 ... 12}
定義では元の情報にラベルを付けるために複数の注釈を使用していますが、実際に重要な注釈は3つだけです。
- @Configuration(@SpringBootConfigurationクリックして表示し、@ Configurationがまだ適用されていることを確認します)
- @EnableAutoConfiguration
- @ComponentScan
つまり、@ SpringBootApplication =(デフォルトのプロパティ)@Configuration + @EnableAutoConfiguration+@ComponentScan。
したがって、次のSpringBootスタートアップクラスを使用する場合でも、SpringBootアプリケーション全体は以前のスタートアップクラスと機能的に同等である可能性があります。
1 @Configuration 2 @EnableAutoConfiguration 3 @ComponentScan 4 public class Application { 5 public static void main(String [] args){ 6 SpringApplication.run(Application.class、args); 7} 8}
毎回これら3つを書くのは面倒なので、@SpringBootApplicationを書くと便利です。次に、これら3つのアノテーションを個別に紹介します。
1、@構成
ここでの@Configurationは、私たちにとってなじみのないものではありません。これは、JavaConfigの形式でSpring Iocコンテナの構成クラスによって使用される@Configurationです。SpringBootコミュニティでは、JavaConfigに基づく構成フォームを使用することをお勧めします。 @Configurationでマークされています。これは、実際にはIoCコンテナの構成クラスです。
確認する簡単な例をいくつか挙げると、XMLと構成の構成方法の違いは次のとおりです。
(1)表現のレベル
XMLベースの構成は次のようになります。
1 <?xml version = "1.0" encoding = "UTF-8"?> 2 <beans xmlns = "http://www.springframework.org/schema/beans" 3 xmlns:xsi = "http://www。 w3.org/2001/XMLSchema-instance " 4 xsi:schemaLocation =" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd " 5 default-lazy-init =" true "> 6 <!-bean定义-> 7 </ Beans>
JavaConfigに基づく構成は次のようになります。
1 @Configuration 2 public class MockConfiguration{ //bean定义 4}
@Configurationで注釈が付けられたJavaクラス定義は、JavaConfig構成クラスです。
(2)Bean定義レベルの登録
XMLベースの構成は次の形式です。
1 <bean id = "mockService" class = ".. MockServiceImpl"> 2 ... 3 </ bean>
JavaConfigに基づく構成は次のようになります。
1 @Configuration 2 public class MockConfiguration { 3 @Bean 4 public MockService mockService(){ 5 return new MockServiceImpl(); 6} 7}
@Beanでマークされたメソッドの場合、その戻り値はSpringのIoCコンテナーにBean定義として登録され、メソッド名はデフォルトでBean定義のIDになります。
(3)依存性注入関係レベルを表現する
BeanとBeanの間の依存関係を表現するために、一般的にXML形式で次のようになります。
1 <bean id = "mockService" class = ".. MockServiceImpl"> 2 <propery name = "dependencyService" ref = "dependencyService" /> 3 </ bean> 4 5 <bean id = "dependencyService" class = "DependencyServiceImpl" > </ bean>
JavaConfigに基づく構成は次のようになります。
1 @Configuration 2 public class MockConfiguration { 3 @Bean 4 public MockService mockService(){ 5 return new MockServiceImpl(dependencyService()); 6} 7 8 @Bean 9 public DependencyServicedependencyService(){ 10 return new DependencyServiceImpl(); 11} 12}
Beanの定義が他のBeanに依存している場合は、対応するJavaConfigクラスで依存Beanの作成メソッドを直接呼び出すことができます。
@Configuration:@Configurationに言及するということは、彼のパートナーである@Beanに言及することを意味します。これらの2つのアノテーションを使用して、対応するxml構成ファイルを置き換えるために使用できる単純なSpring構成クラスを作成できます。
1 <beans> 2 <bean id = "car" class = "com.test.Car"> 3 <property name = "wheel" ref = "wheel"> </ property> 4 </ bean> 5 <bean id = "wheel" class = "com.test.Wheel"> </ bean> 6 </ Beans>
と同等です:
1 @Configuration 2 public class Conf { 3 @Bean 4 public Car car(){ 5 Car car = new Car(); 6 car.setWheel(wheel()); 7帰りの車; 8} 9 10 @Bean 11 public Wheel Wheel(){ 12 return new Wheel(); 13} 14}
@Configuration注釈付きクラスは、このクラスがBean定義のソースとしてSpringIoCコンテナーを使用できることを識別します。
@Beanアノテーションは、@ Beanアノテーションが付けられたメソッドが、SpringアプリケーションコンテキストでBeanとして登録する必要があるオブジェクトを返すことをSpringに通知します。
2、@ ComponentScan
@ComponentScanアノテーションは、Springで非常に重要です。これは、XML構成の要素に対応します。@ ComponentScanの機能は、修飾されたコンポーネント(@Componentや@Repositoryなど)またはBean定義を自動的にスキャンしてロードすることです。最後にこれらのBeanを定義します。IoCコンテナにロードされます。
basePackagesなどの属性を介して@ComponentScan自動スキャンのスコープを細かくカスタマイズできます。指定されていない場合、デフォルトのSpring Framework実装は、@ComponentScanが配置されているクラスを宣言するパッケージからスキャンします。
注:basePackagesはデフォルトで指定されていないため、SpringBootのスタートアップクラスはルートパッケージの下に配置するのが最適です。
3、@EnableAutoConfiguration
個人的には、@ EnableAutoConfigurationが最も重要なアノテーションだと感じているので、最後に解釈します。名前が@Enableで始まるSpringフレームワークによって提供されるアノテーション定義をまだ覚えていますか?たとえば、@ EnableScheduling、@ EnableCaching、@ EnableMBeanExportなど、@ EnableAutoConfigurationの概念と実行方法は、実際には同じ行にあります。簡単な要約では、@ Importのサポートにより、特定のシナリオに関連するBean定義が収集されます。と登録。
- @EnableSchedulingは、@Importを介してSpringスケジューリングフレームワーク関連のBean定義をIoCコンテナーにロードします。
- @EnableMBeanExportは、@Importを介してJMX関連のBean定義をIoCコンテナにロードします。
また、@ EnableAutoConfigurationは、@ Importのヘルプを使用して、自動構成条件を満たすすべてのBean定義をIoCコンテナーにロードします。これですべてです。
@EnableAutoConfigurationは、クラスパスのjar依存関係に従ってプロジェクトを自動的に構成します。たとえば、spring-boot-starter-web依存関係を追加すると、TomcatとSpring MVCの依存関係が自動的に追加され、SpringBootはTomcatとSpringMVCを自動的に構成します。
@EnableAutoConfigurationは、複合アノテーションとして、独自のキー情報を次のように定義します。
1 @SuppressWarnings( "deprecation") 2 @Target(ElementType.TYPE) 3 @Retention(RetentionPolicy.RUNTIME) 4 @Documented 5 @Attached 6 @AutoConfigurationPackage 7 @Import(EnableAutoConfigurationImportSelector.class) 8 public @interface EnableAutoConfiguration{ 9.。 。10 }
その中で最も重要なのは@Import(EnableAutoConfigurationImportSelector.class)です。EnableAutoConfigurationImportSelectorを使用すると、@ EnableAutoConfigurationは、SpringBootアプリケーションがすべての修飾された@Configuration構成を現在のSpringBootによって作成および使用されるIoCコンテナーにロードするのに役立ちます。「タコ」のように、Springフレームワークの元のツールクラスであるSpringFactoriesLoaderをサポートすることで、@ EnableAutoConfigurationは関数をインテリジェントに自動的に構成でき、完了です。
自動構成の背後にあるヒーロー:SpringFactoriesLoaderの詳細
SpringFactoriesLoaderは、Springフレームワークのプライベート拡張スキームであり、その主な機能は、指定された構成ファイルMETA-INF/spring.factoriesから構成をロードすることです。
1 public abstract class SpringFactoriesLoader { 2 // ... 3 public static <T> List <T> loadFactories(Class <T> factoryClass、ClassLoader classLoader){ 4 ... 5} 6 7 8 public static List <String> loadFactoryNames (Class <?> factoryClass、ClassLoader classLoader){ 9 .... 10} 11}
@EnableAutoConfigurationと一緒に使用すると、構成ルックアップのサポートが強化されます。つまり、ルックアップするキーとして@EnableAutoConfiguration org.springframework.boot.autoconfigure.EnableAutoConfigurationの完全なクラス名に従って、対応する@Configurationクラスのセットを取得します。 。
上の図は、SpringBootのautoconfigure依存関係パッケージに含まれるMETA-INF / spring.factories構成ファイルからの抜粋であり、問題をうまく説明できます。
したがって、@EnableAutoConfigurationによって自動的に構成される魔法の騎士は次のようになります。クラスパスからすべてのMETA-INF/ spring.factories構成ファイルを検索し、org.springframework.boot.autoconfigure.EnableutoConfigurationに対応する構成アイテムをリフレクション(Java Refletion)を介して渡します。 @ConfigurationでマークされたJavaConfigの形式で対応するIoCコンテナー構成クラスとしてインスタンス化され、1つに集約されて、IoCコンテナーにロードされます。
次に、SpringApplication実行プロセスの詳細な調査
SpringApplicationのrunメソッドの実装は、私たちの旅の主なルートです。このメソッドの主なプロセスは、次のように大まかに要約できます。
1)SpringApplicationの静的runメソッドを使用している場合、このメソッドは最初にSpringApplicationオブジェクトのインスタンスを作成し、次に作成されたSpringApplicationのインスタンスメソッドを呼び出します。SpringApplicationインスタンスが初期化されると、事前にいくつかのことが行われます。
- クラスパスに特性クラス(org.springframework.web.context.ConfigurableWebApplicationContext)があるかどうかに応じて、Webアプリケーションで使用されるApplicationContextタイプを作成するかどうかが決定されます。
- SpringFactoriesLoaderを使用して、アプリケーションのクラスパスで使用可能なすべてのApplicationContextInitializersを検索してロードします。
- SpringFactoriesLoaderを使用して、アプリケーションのクラスパスで使用可能なすべてのApplicationListenerを検索してロードします。
- mainメソッドの定義クラスを推測して設定します。
2)SpringApplicationインスタンスが初期化され、設定が完了すると、runメソッドのロジックが実行されます。メソッド実行の開始時に、SpringFactoriesLoaderを介して検出およびロードできるすべてのSpringApplicationRunListenersが最初にトラバースされ、実行されます。彼らのstarted()メソッドを呼び出すと、これらのSpringApplicationRunListenersに「ねえ、SpringBootアプリケーションが実行を開始しようとしています!」と通知します。
3)現在のSpring Bootアプリケーションが使用する環境を作成して構成します(使用するPropertySourceとプロファイルの構成を含む)。
4)すべてのSpringApplicationRunListenerを呼び出すenvironmentPrepared()メソッドをトラバースし、「現在のSpringBootアプリケーションで使用される環境の準備ができました!」と伝えます。
5)SpringApplicationのshowBannerプロパティがtrueに設定されている場合は、バナーを印刷します。
6)ユーザーがapplicationContextClassタイプと初期化フェーズの推論結果を明確に設定したかどうかに応じて、現在のSpringBootアプリケーションに対して作成するApplicationContextのタイプを決定し、それを作成してから、条件に従ってShutdownHookを追加するかどうかを決定します。 、カスタムBeanNameGeneratorを使用するかどうかを決定し、カスタムResourceLoaderを使用するかどうかを決定します。もちろん、最も重要なことは、事前に準備した環境を作成したApplicationContextに設定することです。
7)ApplicationContextが作成された後、SpringApplicationはSpring-FactoriesLoaderを再度使用して、クラスパスで使用可能なすべてのApplicationContext-Initializersを見つけてロードし、これらのApplicationContextInitializersのinitialize(applicationContext)メソッドをトラバースして呼び出し、作成されたApplicationContextをさらに処理します。
8)すべてのSpringApplicationRunListener呼び出しのcontextPrepared()メソッドをトラバースします。
9)コアステップは、@EnableAutoConfigurationおよび他の形式のIoCコンテナ構成を通じて取得されたすべての構成を準備されたApplicationContextにロードすることです。
10)すべてのSpringApplicationRunListener呼び出しのcontextLoaded()メソッドをトラバースします。
11)ApplicationContextのrefresh()メソッドを呼び出して、IoCコンテナーで使用可能な最後のプロセスを完了します。
12)CommandLineRunnerが現在のApplicationContextに登録されているかどうかを確認し、登録されている場合は、それらをトラバースして実行します。
13)通常の状況では、SpringApplicationRunListenerのfinished()メソッドをトラバースして実行します(プロセス全体が異常な場合でも、すべてのSpringApplicationRunListenerのfinished()メソッドが呼び出されますが、この場合、例外情報は次のように渡されます。処理)
イベント通知ポイントを削除した後のプロセス全体は次のとおりです。
この記事では、実際のSpringBootスタートアッププログラムのデバッグを例として取り上げ、そのスタートアップロジックと自動構成の原則を分析するために、プロセスのメインクラス図を参照します。
概要:
上の図は、SpringBootの起動構造図を示しています。起動プロセスは主に3つの部分に分かれています。最初の部分は、SpringApplicationの初期化モジュールであり、いくつかの基本的な環境変数、リソース、コンストラクター、およびリスナーが構成されています。一部はアプリケーション固有を実現します。起動スキームには、起動プロセスの監視モジュール、ロード構成環境モジュール、およびコア作成コンテキスト環境モジュールが含まれます。3番目の部分は、springboot自動構成のコアである自動構成モジュールです。以下の分析で詳細に説明します。以下のスターターでは、構造内の主な機能をチェーンします。
起動:
各SpringBootプログラムには、メインエントリ、つまりmainメソッドがあります。メインでは、SpringApplication.run()が呼び出され、Spring-Bootプログラム全体が開始されます。メソッドが配置されているクラスは、@SpringBootApplicationアノテーションを使用する必要があります。 @ImportResourceアノテーション(必要な場合)、@ SpringBootApplicationには、次の関数を持つ3つのアノテーションが含まれています。
@EnableAutoConfiguration:SpringBootは、アプリケーションによって宣言された依存関係に基づいてSpringフレームワークを自動的に構成します。
@SpringBootConfiguration(内部的には@Configuration):マークされたクラスは、すべてのBeanトランザクションをアセンブルしてSpringコンテキストを提供するSpring XML構成ファイル(applicationContext.xml)と同じです。
@ComponentScan:Beanを自動的に検出してアセンブルできるコンポーネントスキャンデフォルトでは、SpringApplicationのrunメソッドのBooter.classのパッケージパスにあるファイルがスキャンされるため、スタートアップクラスをルートパッケージパスに配置するのが最適です。 。
SpringBootスタートアップクラス
最初にrunメソッドを入力します
SpringApplicationインスタンスはrunメソッドで作成されます。このコンストラクターでは、初期化された初期化メソッドを呼び出すことがわかります。
これは主に、SpringApplicationオブジェクトにいくつかの初期値を割り当てるためのものです。コンストラクターが実行された後、runメソッドに戻ります
このメソッドでは、次の主要な手順が実装されています。
1.アプリケーションのリスナーSpringApplicationRunListenersを作成し、リッスンを開始しました
2. SpringBoot構成環境(ConfigurableEnvironment)をロードします。これがWebコンテナーを介して公開されている場合は、最終的にConfigurableEnvironmentを継承するStandardEnvironmentがロードされ、クラス図は次のようになります。
* Environmentが最終的にPropertyResolverインターフェースを実装していることがわかります。通常、環境オブジェクトを介して構成ファイルで指定されたKeyに対応するvalueメソッドを取得する場合、propertyResolverインターフェースのgetPropertyメソッドを呼び出します。
3.構成環境(Environment)がリスナーオブジェクト(SpringApplicationRunListeners)に追加されます
4. runメソッドの戻りオブジェクトを作成します:ConfigurableApplicationContext(アプリケーション構成コンテキスト)。作成メソッドを確認できます。
このメソッドは、最初に明示的に設定されたアプリケーションコンテキスト(applicationContextClass)を取得します。存在しない場合は、デフォルトの環境構成をロードし(Web環境かどうかで判断)、デフォルトでAnnotationConfigApplicationContextアノテーションコンテキストを選択します(すべてのアノテーションクラスをスキャンします)。 Beanをロードするため)、最後にBeanUtilsを介してコンテキストオブジェクトをインスタンス化し、それを返します。
ConfigurableApplicationContextクラス図は次のとおりです。
それは主にその継承の2つの方向に依存します:
ライフサイクル:開始開始、停止終了、isRunningを定義するライフサイクルクラスは、中程度のライフサイクルのnull値メソッドを実行するかどうかを実行します
ApplicationContext:主にbeanFactory(beanファクトリクラス)を継承するアプリケーションコンテキストクラス
5. runメソッドに戻ると、prepareContextメソッドは、リスナー、環境、applicationArguments、バナーなどの重要なコンポーネントをコンテキストオブジェクトに関連付けます。
6.次のrefreshContext(context)メソッド(初期化メソッドは次のとおりです)は、spring.factoriesのロードを含むspring-boot-starter- *(mybatis、redisなど)の自動構成を実現するための鍵になります。 、Beanおよびその他のコアタスクのインスタンス化。
構成が完了すると、Springbootはいくつかの基本的な仕上げ作業を行い、アプリケーション環境のコンテキストを返します。プロセス全体を振り返ると、Springbootの起動は、主に構成環境(environment)、イベントリスナー(listeners)、およびアプリケーションコンテキスト(applicationContext)を作成し、上記の条件に基づいて、コンテナーで必要なBeanのインスタンス化を開始します。 、これまでのところ、SpringBootの起動を通じてプログラムが構築されました。自動構成の実装方法について説明しましょう。
自動構成:
前のスタートアップ構造図では、アプリケーションの初期化と特定の実行プロセスの両方がSpringBoot自動構成モジュールを呼び出すことに気づきました。
SpringBoot自動構成モジュール
この構成モジュールの主な用途は、SpringFactoriesLoader、つまりSpringファクトリローダーです。このオブジェクトはloadFactoryNamesメソッドを提供します。入力パラメーターはfactoryClassとclassLoaderです。つまり、上の図のファクトリクラス名と対応するクラスローダーが必要です。メソッドは、指定されたclassLoaderに基づいて、クラス加算器の検索パスの下に指定されたファイル、つまりspring.factoriesファイルをロードします。着信ファクトリクラスはインターフェイスであり、対応するクラスはfileは、インターフェイスの実装クラス、または最終的には実装クラスであるため、次の図に示すように、ファイルは通常、クラス名の1対多のコレクションです。これらの実装クラスのクラス名を取得した後、loadFactoryNamesメソッドはクラス名のコレクションを返します。メソッド呼び出し元がこれらのコレクションを取得した後、リフレクション、構築メソッドを介してこれらのクラスのクラスオブジェクトを取得し、最後にインスタンスを生成します。
ファクトリインターフェイスとその実装クラスインターフェイス名の一部
次の図は、自動構成プロセスを視覚化するのに役立ちます。
SpringBoot自動構成キーコンポーネント図
mybatis-spring-boot-starterやspring-boot-starter-webなどのコンポーネントのMETA-INFファイルにはすべてspring.factoriesファイルが含まれています。自動構成モジュールでは、SpringFactoriesLoaderがファイル内の完全なクラス名を収集し、完全なものを返します。クラス名返されるクラスのフルネームは、リフレクションによってインスタンス化されて特定のファクトリインスタンスを形成し、ファクトリインスタンスはコンポーネントに必要なBeanを生成するために使用されます。
EnableAutoConfigurationアノテーションについて説明する前に、そのクラス図は次のとおりです。
AutoConfigurationImportSelectorのselectImportsメソッドに焦点を当てて、最終的にImportSelector(セレクター)とBeanClassLoaderAware(Beanクラスローダーミドルウェア)を実装していることがわかります。
このメソッドは、springboot起動プロセス(Beanのインスタンス化)の前に実行され、インスタンス化されるクラス情報のリストを返します。クラス情報が取得されると、Springはクラスローダーを介してクラスをjvmに自然にロードできることがわかっています。これで、spring-bootのスターター依存関係を通じて必要なコンポーネントに依存するようになり、これらのコンポーネントのクラス情報は次のようになります。選択した方法で取得することもできますので、ご安心ください。分析を続けます。
このメソッドのgetCandidateConfigurationsメソッドは、メソッドアノテーションを通じて学習され、自動構成クラスのクラス名のリストを返します。メソッドはloadFactoryNamesメソッドを呼び出し、メソッドを確認します。
上記のコードでは、自動構成ツールが、着信するfactoryClass.getName()に従って、プロジェクトシステムパスの下にあるすべてのspring.factoriesファイルで対応するキーを見つけて、内部のクラスをロードすることがわかります。このmybatis-spring-boot-autoconfigureの下でspring.factoriesファイルを選択します
org.mybatis.spring.boot.autoconfigure.MybatisAutoConfigurationと入力し、主にクラスヘッダーを確認します。
Springの@Configurationは、アノテーションが付けられたSpringBeanのようなものであり、見下ろし続けていることがわかりました。
@ConditionalOnClass({SqlSessionFactory.class、SqlSessionFactoryBean.class})このアノテーションは、次のことを意味します。MybatisAutoConfiguration構成クラスは、SqlSessionFactory.classとSqlSessionFactoryBean.classが存在する場合にのみ解析されます。それ以外の場合、この構成クラスは解析されません。セッションオブジェクトなので、セッションファクトリ関連のクラスが必要です。
@CondtionalOnBean(DataSource.class):Beanとして宣言されたdataSourceのみを処理します。
@ConditionalOnMissingBean(MapperFactoryBean.class)このアノテーションは、名前で指定されたBeanがコンテナに存在しない場合、Beanインジェクションが作成され、それ以外の場合は実行されないことを意味します(このクラスのソースコードは長く、スペース制限があります)完全に貼り付けられていません)
上記の構成により、sqlSessionFactory、sqlSessionTemplate、dataSourceなどのmybatisに必要なコンポーネントを自動的に構成できるようになります。@ ConfigurationアノテーションはSpringのコンテキストを提供しているため、上記のコンポーネントの構成は、 Springが起動したときのmybatis.xmlファイル。分析の結果、SpringBootプロジェクトに基づくクラスパスにSqlSessionFactory.class、SqlSessionFactoryBean.classがあり、dataSourceBeanがコンテナーに登録されている限り、自動構成をトリガーできることがわかります。つまり、 mybatisをmavenプロジェクトに追加する必要があります。必要な依存関係によって自動構成がトリガーされる可能性がありますが、mybatisのネイティブ依存関係が導入された場合、統合された機能ごとに自動構成クラスを変更する必要があります。取得できません。そのため、Spring-bootは、関連するクラスを直接構成できる統合スターターを提供します。自動構成をトリガーするために必要な依存関係(mybatis)は次のとおりです。
傍受されたmybatis-spring-boot-starterのソースコードにあるpom.xmlファイルのすべての依存関係は次のとおりです。
Mavenの依存関係は推移的であるため、すぐに使用できる機能を実現するためにスターターに依存している限り、自動的に構成する必要のあるすべてのクラスに依存できます。また、Springbootは、Springフレームワークによってもたらされる多数のXML構成と複雑な依存関係管理を簡素化し、開発者がビジネスロジックの開発により多くの注意を払うことを可能にすることも反映しています。