SpringApplicationクラスの初期化プロセス:プロセス分析(A)を起動SpringBoot

SpringBootシリーズの紹介

SpringBoot補助ソースは、記事をお読みください。

  設計と実装のIoCコンテナSpringアプリケーションコンテキストと

プロセスのソースコードの解析を開始しSpringBoot:

  1. SpringApplicationクラスの初期化プロセス:プロセス分析(A)を起動SpringBoot
  2. SpringApplicationのrunメソッド:プロセス分析(B)を起動SpringBoot
  3. ()メソッドのSpringApplicationのprepareContext実行方法:プロセス分析(III)を起動SpringBoot
  4. 初期化プロセスIoCコンテナ:プロセス分析(D)を起動SpringBoot
  5. プロセス分析(V)を開始SpringBoot:SpringBootは自動組立の原理を実装します
  6. IoCの依存性注入コンテナ:プロセス分析(VI)を起動しSpringBoot

作者のコメント版SpringBootソースのSpring Frameworkとgitのポータル:小さな星を意味しないでください

  1. 春・フレームワーク5.0.8.RELEASE
  2. SpringBoot-2.0.4.RELEASE

、SpringApplicationの初期化プロセス

  1.1、SpringBootプロジェクトミアン機能

  クラスのメインルーチンは、以下に示すように、私たちは通常、書き込みに行きます。

 

  このクラスでは、に焦点を当てる必要があります

  • @SpringBootApplication
  • SpringApplication.run()

@SpringBootApplicationの  ノート、後で分析SpringBoot自動組立のセクションでは、分析を開始します。

  我々は、このセクションに集中する必要が  SpringApplication.run()  メソッド。

  run()メソッドは、次のコードに示すように、我々はそれが最初に作成されていることを見つけるビュー達成  SpringApplicationの  インスタンスを、その呼び出し  SpringApplication  run()メソッドを、私たちは、この章であることを懸念している  SpringApplicationは  、インスタンスを作成するプロセス。

/ ** 
     * {実行するために使用することができる静的ヘルパー@link からSpringApplication} 
     デフォルト設定とユーザ指定された引数を使用して、*指定されたソース。
     * 
     * @paramをロードする一次ソースをprimarySources 
     * @paramは(通常のJava mainメソッドから渡された)アプリケーションの引数をARGS 
     * @return 実行{ @link のApplicationContext}
      * / 
    パブリック 静的 ConfigurableApplicationContextラン(クラス<?> [] primarySources 、
                                                     文字列[]引数){ 
        リターン 新しいSpringApplication(primarySources).RUN(引数); 
    }

   

  1.2、  SpringApplication()  コンストラクタ

  ソースコードを表示し続け、  SpringApplicationの  インスタンス化プロセスが、すべての最初は、コンストラクタのパラメータを入力することで、最終的に戻ってコンストラクタに二つのパラメータ。

1  公共 SpringApplication(クラス<?> ... primarySources){
 2      ヌル、primarySources)。
3  }
 4  
5 @SuppressWarnings({ "未チェック"、 "rawtypes" })
 6  公共 SpringApplication(ResourceLoader resourceLoader、クラス<?> ... primarySources){
 7      この .resourceLoader = resourceLoader。
8      Assert.notNull(primarySources、 "PrimarySourcesがnullであってはなりません" )。
9      この .primarySources = 新しい LinkedHashSetの<> は、Arrays.asList(primarySources))。
10     // 対応するタイプは、以降の環境に依存します初期化、アプリケーションの種類を推測します。一般的に使用されているサーブレット環境
11。     この .webApplicationType = deduceWebApplicationType(); // 2.2.1
 12である     // CLASSPATHに構成ApplicationContextInitializer META-INF / spring.factories初期化
13であるが      。SetInitializers((コレクション)getSpringFactoriesInstances(ApplicationContextInitializerのクラス)); 2.2.2 //
 14      // 設定されたすべてのクラスパスを初期化ApplicationListener 
15      setListeners((コレクション)getSpringFactoriesInstances(ApplicationListener。クラス)); 2.2.3 //
 16      // 推定の呼び出しスタック、mainメソッドクラス名
。17      この .mainApplicationClass =deduceMainApplicationClass();
18 }

 

   型推論の適用方法; 1.2.1、deduceWebApplicationType()。 SERVLET REACTIVE NONEません 

1  // 常量值
2  プライベート 静的 最終列[] WEB_ENVIRONMENT_CLASSES = { "のjavax.servlet.Servlet" 3              "org.springframework.web.context.ConfigurableWebApplicationContext" }。
4  
5  プライベート 静的な 最終文字列REACTIVE_WEB_ENVIRONMENT_CLASS = "org.springframework。"
6          + "web.reactive.DispatcherHandler" 7  
8  プライベート 静的な 最終文字列MVC_WEB_ENVIRONMENT_CLASS = "org.springframework。"
9          + "web.servlet.DispatcherServlet"  
 プライベート 静的 最終列JERSEY_WEB_ENVIRONMENT_CLASS =「org.glassfish.jersey.server.ResourceConfig」;
 12は、 
13である / ** 
14  *アプリケーションの種類を判断する
 15  * NONE:アプリケーションがWebアプリケーションではないが、ウェブ・サーバは、起動するために使用されるべきではない
 16  *サーブレット:アプリケーションは、サーブレットベースのWebアプリケーションとして実行する必要があり、および組み込みサーブレットウェブ(Tomcatの)サーバを起動する必要があります。
17  *反応性:アプリケーションは、反応性のWebアプリケーションとして実行する必要があり、そして組み込み反応性のWebサーバを起動する必要があります。
18は * @return 
。19   * / 
20  プライベートWebApplicationType deduceWebApplicationType({)
 21である     //が存在CLASSPATH org.springframework.web.reactive.DispatcherHandlerなければならない
22は     IF(ClassUtils.isPresent(REACTIVE_WEB_ENVIRONMENT_CLASS、NULL 23              !&& ClassUtils.isPresent(MVC_WEB_ENVIRONMENT_CLASS、NULL 24              !&& ClassUtils.isPresent(JERSEY_WEB_ENVIRONMENT_CLASS、NULL )){
 25          リターンWebApplicationType.REACTIVE。
26      }
 27      のために(文字列クラス名:WEB_ENVIRONMENT_CLASSES){
 28          であれば(!ClassUtils.isPresent(クラス名、NULL )){
 29              リターンWebApplicationType.NONE。
30          }
 31      }
 32      //クラスパス周囲にjavax.servlet.Servlet存在またはorg.springframework.web.context.ConfigurableWebApplicationContext 
33が     戻りWebApplicationType.SERVLETを、
 34です }

  戻り型はWebApplicationType、タイプ列挙さ  WebApplicationType  列挙請求項3つの注釈を説明したように、三つの列挙します

  次のように特定決意ロジックがあります。

  • WebApplicationType.REACTIVEクラスパス下存在org.springframework.web.reactive.DispatcherHandler

  • WebApplicationType.SERVLETクラスパス下存在にjavax.servlet.Servlet或者org.springframework.web.context.ConfigurableWebApplicationContext

  • WebApplicationType.NONEは、上記の条件を満たしていません。

  

  1.2.2、setInitializers((コレクション)getSpringFactoriesInstances(ApplicationContextInitializer.class)); 

  すでに設定されているクラスパスApplicationContextInitializer META-INF / spring.factoriesの初期化。

1  プライベート <T>コレクション<T> getSpringFactoriesInstances(クラス<T> 型){
 2      戻り getSpringFactoriesInstances(タイプ、新しい新しいクラス<?> [] {});
 3  }
 4。 
5。 / ** 
6。 * METAクラスローダによって指定されました-INF / spring.factoriesスプリングは、工場の特定のインスタンスを取得する
 。7  * @paramのタイプ
 。8  * @param たparameterTypes
 。9  * @paramの引数
 10  * @param <T>
 。11  * @return 
12である  * / 
13であり、 プライベート<T>コレクション<T> getSpringFactoriesInstances(クラス<T> 型、
 14                                                        クラス<?> [] parameterTypesパラメータ、...オブジェクト引数){
 15      のClassLoaderクラスローダ= にThread.currentThread()getContextClassLoader();.
 16      // 使用名Ensure®と重複から保護するためにUNIQUE
 。17      // spring.factoriesクラスローダによって指定されたMETA-INF /リソースファイルから、
 18である     // 読みキーがtype.getName(ある)値の
19      セットの<文字列> =名前の新しい新しい LinkedHashSetの<> (SpringFactoriesLoader.loadFactoryNames(タイプ、クラスローダ));
 20である     // インスタンススプリング植物を作成します
21は      リスト<T> =インスタンスcreateSpringFactoriesInstances(タイプ、parameterTypesパラメータ、
 22は             クラスローダ、引数、名前)は、
 23である     // 植物スプリングソーティング例えば(org.springframework.core.annotation.Order順序が注釈を指定)
24      AnnotationAwareOrderComparator.sort(インスタンス);
 25の     戻りインスタンス;
 26です }

 

  見て  getSpringFactoriesInstancesの  何かが非常に重要なメソッドがあり、ソースコードを見て、行って  )(loadFactoryNames  であるこの方法は、META-INF / spring.factories指定されたクラスから(キー)を撮影した春・コアで提供され、この方法は非常に重要です同じ入力方法。

ここでは、アクセスがへの鍵である  org.springframework.context.ApplicationContextInitializerの  クラス。

  デバッグすべてが何を見てもらいます

 

  上記、META-INFから取得されることを特徴と/クラスパスをspring.factories、我々は確認してください。

  发现在上图所示的两个工程中找到了debug中看到的6条结果。 ApplicationContextInitializer 是Spring框架的类, 这个类的主要目的就是在   ConfigurableApplicationContext 调用refresh()方法之前,回调这个类的initialize方法。通过  ConfigurableApplicationContext 的实例获取容器的环境Environment,从而实现对配置文件的修改完善等工作。

  关于怎么实现自定义的 ApplicationContextInitializer 请看我的另一篇专门介绍该类的博客

 

  1.2.3、 setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); 

  初始化classpath下 META-INF/spring.factories中已配置的 ApplicationListener。

   ApplicationListener 的加载过程和上面的 ApplicationContextInitializer 类的加载过程是一样的。不多说了,至于 ApplicationListener 是spring的事件监听器,典型的观察者模式,通过 ApplicationEvent 类和 ApplicationListener 接口,可以实现对spring容器全生命周期的监听,当然也可以自定义监听事件。为了梳理springboot的启动流程在这里先不说这个了。后面有时间的话再介绍。

   关于ApplicationContextInitializer的详细介绍请看<SpringBoot之ApplicationContextInitializer的理解和使用>

 二、总结

  关于 SpringApplication 类的构造过程,到这里我们就梳理完了。纵观 SpringApplication 类的实例化过程,我们可以看到,合理的利用该类,我们能在spring容器创建之前做一些预备工作,和定制化的需求。

比如,自定义SpringBoot的Banner,比如自定义事件监听器,再比如在容器refresh之前通过自定义 ApplicationContextInitializer 修改配置一些配置或者获取指定的bean都是可以的。。。

  下一节开始分析SpringBoot容器的构建过程,也就是那个大家多少都看过的run();方法。

   

  原创不易,转载请注明出处。

  如有错误的地方还请留言指正。

おすすめ

転載: www.cnblogs.com/hello-shf/p/10976646.html