SpringBootシリーズの紹介
SpringBoot補助ソースは、記事をお読みください。
設計と実装のIoCコンテナSpringアプリケーションコンテキストと
プロセスのソースコードの解析を開始しSpringBoot:
- SpringApplicationクラスの初期化プロセス:プロセス分析(A)を起動SpringBoot
- SpringApplicationのrunメソッド:プロセス分析(B)を起動SpringBoot
- ()メソッドのSpringApplicationのprepareContext実行方法:プロセス分析(III)を起動SpringBoot
- 初期化プロセスIoCコンテナ:プロセス分析(D)を起動SpringBoot
- プロセス分析(V)を開始SpringBoot:SpringBootは自動組立の原理を実装します
- IoCの依存性注入コンテナ:プロセス分析(VI)を起動しSpringBoot
作者のコメント版SpringBootソースのSpring Frameworkとgitのポータル:小さな星を意味しないでください
、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();方法。
原创不易,转载请注明出处。
如有错误的地方还请留言指正。