SpringBoot実行処理例分析
各 Spring Boot プロジェクトにはメイン プログラムの起動クラスがあり、メイン プログラムの起動クラスにはプロジェクトを起動する main() メソッドがあり、このメソッドでは SpringApplication.run を実行することで Spring Boot プログラム全体を起動できます() 。
質問: SpringApplication.run() メソッドはどのようにして Spring Boot プロジェクトを開始するのでしょうか?
run() メソッド内のソース コードを見てみましょう。コア コードは次のとおりです:
@SpringBootApplication public class SpringbootDemoApplication { public static void main(String[] args) { SpringApplication.run(SpringbootDemoApplication.class, args); } }
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) { return run(new Class[]{primarySource}, args); } public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) { return (new SpringApplication(primarySources)).run(args); }
上記のソース コードからわかるように、SpringApplication.run() メソッドはは、それぞれ 2 つの操作を実行します。これは、SpringApplication インスタンスの最初の作成と、プロジェクトを開始するための run() の呼び出しです。これら 2 つの段階の実装の詳細は、次のとおりです。
1. SpringApplication インスタンスの初期作成
SpringApplication インスタンス オブジェクトの初期化と作成のソース コード情報を表示します。コア コードは次のとおりです
public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) { this.sources = new LinkedHashSet(); this.bannerMode = Mode.CONSOLE; this.logStartupInfo = true; this.addCommandLineProperties = true; this.addConversionService = true; this.headless = true; this.registerShutdownHook = true; this.additionalProfiles = new HashSet(); this.isCustomEnvironment = false; this.resourceLoader = resourceLoader; Assert.notNull(primarySources, "PrimarySources must not be null"); // 把项目启动类.class设置为属性存储起来 this.primarySources = new LinkedHashSet(Arrays.asList(primarySources)); // 判断当前webApplicationType应用的类型 this.webApplicationType = WebApplicationType.deduceFromClasspath(); // 设置初始化器(Initializer),最后会调用这些初始化器 this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class)); // 设置监听器(Listener) this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class)); // 用于推断并设置项目main()方法启动的主程序启动类 this.mainApplicationClass = this.deduceMainApplicationClass();
上記のソース コードからわかるように、初期化SpringApplication の処理は主に 4 つの部分で構成されており、詳細は以下のとおりです。
(1) this.webApplicationType = WebApplicationType.deduceFromClasspath()
は、現在の webApplicationType アプリケーションの種類を決定するために使用されます。 deduceFromClasspath() メソッドは、特定のフィーチャークラスが Classpath クラスパスの下に存在するかどうかをチェックし、現在の webApplicationType タイプが SERVLET アプリケーション (Spring 5 より前の従来の MVC アプリケーション) であるか REACTIVE アプリケーション (WebFlux 対話型アプリケーション) であるかを判断するために使用されます。 Spring 5 で登場し始めた)
(2) this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class))
SpringApplication アプリケーションの初期化設定。イニシャライザの設定プロセス中に、Spring クラス ローダ SpringFactoriesLoader を使用して、META-INF/spring.factories クラス パスの META-INF にある spring.factores ファイルから利用可能なすべてのアプリケーション初期化クラス ApplicationContextInitializer を取得します。
(3) this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class))
SpringApplicationアプリケーションのリスナー設定に使用されます。リスナーの設定プロセスは、前のステップのイニシャライザの設定プロセスと基本的に同じです。SpringFactoriesLoader は、META-INF/spring.factories クラス パスの META-INF の下にある spring.factores ファイルから、利用可能なすべてのリスナー クラス ApplicationListener を取得するためにも使用されます。 。
(4) this.mainApplicationClass = this.deduceMainApplicationClass()
プロジェクトの main() メソッドによって開始されるメイン プログラムの起動クラスを推論して設定するために使用されます
2.プロジェクトの初期化起動
(new SpringApplication(primarySources)).run(args) ソース コードの前の部分で SpringApplication インスタンス オブジェクトの初期化と作成を分析した後、プロジェクトの初期化起動プロセスを確認し、 run(args) メソッドによって実行されるコア コード 詳細は次のとおりです。
public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList(); this.configureHeadlessProperty(); // 第一步:获取并启动监听器 SpringApplicationRunListeners listeners = this.getRunListeners(args); listeners.starting(); Collection exceptionReporters; try { ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); // 第二步:根据SpringApplicationRunListeners以及参数来准备环境 ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments); this.configureIgnoreBeanInfo(environment); // 准备Banner打印器 - 就是启动Spring Boot的时候打印在console上的ASCII艺术字体 Banner printedBanner = this.printBanner(environment); // 第三步:创建Spring容器 context = this.createApplicationContext(); exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, new Object[]{context}); // 第四步:Spring容器前置处理 this.prepareContext(context, environment, listeners, applicationArguments, printedBanner); // 第五步:刷新容器 this.refreshContext(context); // 第六步:Spring容器后置处理 this.afterRefresh(context, applicationArguments); stopWatch.stop(); if (this.logStartupInfo) { (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch); } // 第七步:发出结束执行的事件 listeners.started(context); // 返回容器 this.callRunners(context, applicationArguments); } catch (Throwable var10) { this.handleRunFailure(context, var10, exceptionReporters, listeners); throw new IllegalStateException(var10); } try { listeners.running(context); return context; } catch (Throwable var9) { this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners) null); throw new IllegalStateException(var9); } }
上記のソース コードからわかるように、プロジェクトの初期化起動プロセスには通常、次の部分が含まれます。ステップ 1: リスナーの取得と開始
#this.getRunListeners (args) メソッドと listens.starting() メソッドは、主に、SpringApplication インスタンスの初期化プロセス中に初期化された SpringApplicationRunListener リスナーを取得して実行するために使用されます。
2 番目のステップ: SpringApplicationRunListeners とパラメーターに基づいて環境を準備する
This.prepareEnvironment(listeners, applicationArguments) メソッドは主にプロジェクトの実行環境をプリセットするために使用され、同時にこれを通じて.configureIgnoreBeanInfo(environment ) メソッドを使用して、不要な実行環境を除外します。
ステップ 3: Spring コンテナを作成します
webApplicationType に基づいてコンテナのタイプを決定します。タイプが SERVLET タイプの場合、対応するコンテナは、リフレクション バイトコード、つまり AnnotationConfigServletWebServerApplicationContext を通じてロードされ、以前に初期化されたコンテキスト (アプリケーション コンテキスト環境)、環境 (プロジェクト実行環境)、リスナー (実行リスナー)、applicationArguments (プロジェクト パラメーター)、printedBanner (プロジェクト アイコン) を使用します。情報) を使用して、アプリケーション コンテキストを作成します。 構成をアセンブルし、構成を更新します。
ステップ 4: Spring コンテナーの前処理
このステップは主に、コンテナーが更新される前の準備アクションです。さまざまな変数などを含むコンテナ環境をセットアップします。これには非常に重要な操作が含まれます。スタートアップ クラスをコンテナに挿入して、後続の自動構成の基礎を築く
ステップ 5: コンテナを更新する
Spring コンテナのリフレッシュを開始し、リフレッシュ メソッドを通じて IOC コンテナ全体を初期化し (Bean リソースの配置、解析、登録などを含む)、JVM ランタイムにシャットダウン フックを登録します。このコンテキストは、JVM が終了すると閉じられます。その時点でない限りシャットダウンされます すでに閉じられています
ステップ 6: Spring コンテナの後処理
拡張インターフェイス、デザイン モードのテンプレート メソッド、デフォルトは空の実装です。カスタム要件がある場合は、このメソッドをオーバーライドできます。たとえば、起動ログと完了ログ、またはその他の後処理を出力します。
ステップ 7: 実行を終了するイベントを発行する
EventPublishingRunListener リスナーを取得してその開始メソッドを実行し、作成した Spring コンテナを渡して ApplicationStartedEvent イベントを作成し、ConfigurableApplicationContext を実行します
publishEvent メソッド、つまりイベントは SpringApplication ではなく Spring コンテナーに発行されます。これは前回の開始とは異なります。前回の開始は SpringApplication のリスナーに直接発行されます。イベントを開始します。
ステップ 8: ランナーの実行
プロジェクト内のカスタム エグゼキュータ XxxRunner クラスを呼び出して、プロジェクトの開始直後に特定のプログラムを実行するために使用されます。 Spring Boot が提供する Executor インターフェイスには、ApplicationRunner と CommandLineRunner があり、使用する場合は、いずれかのインターフェイスを実装するように Executor クラスをカスタマイズし、対応する run() メソッドのインターフェイスを書き換えるだけで、Spring Boot プロジェクトが完成します。これらの特定のプログラムを実行します。
以下の Spring Boot 実行フローチャートを通じて、Spring Boot の全体的な実行プロセスと主な起動段階をより明確に理解してください:
以上がSpringBoot実行処理例分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック

Jasypt の概要 Jasypt は、開発者が最小限の労力で基本的な暗号化機能を自分のプロジェクトに追加できる Java ライブラリであり、暗号化の仕組みを深く理解する必要はありません。一方向および双方向暗号化の高いセキュリティ。標準ベースの暗号化テクノロジー。パスワード、テキスト、数値、バイナリを暗号化します... Spring ベースのアプリケーション、オープン API への統合、JCE プロバイダーでの使用に適しています... 次の依存関係を追加します: com.github.ulisesbocchiojasypt-spring-boot-starter2. 1.1 Jasypt の特典はシステムのセキュリティを保護し、コードが漏洩した場合でもデータ ソースは保証されます。

使用シナリオ 1. 注文は正常に行われましたが、支払いが 30 分以内に行われませんでした。支払いがタイムアウトになり、注文が自動的にキャンセルされました 2. 注文に署名があり、署名後 7 日間評価が行われませんでした。注文がタイムアウトして評価されない場合、システムはデフォルトでプラスの評価を設定します 3. 注文は正常に行われます。販売者が 5 分間注文を受け取らない場合、注文はキャンセルされます。 4. 配送がタイムアウトします。 SMS リマインダーをプッシュします... 遅延が長く、リアルタイム パフォーマンスが低いシナリオでは、タスク スケジュールを使用して定期的なポーリング処理を実行できます。例: xxl-job 今日は選択します

1. Redis は分散ロックの原則を実装しており、分散ロックが必要な理由 分散ロックについて話す前に、分散ロックが必要な理由を説明する必要があります。分散ロックの反対はスタンドアロン ロックです。マルチスレッド プログラムを作成するとき、共有変数を同時に操作することによって引き起こされるデータの問題を回避します。通常、ロックを使用して共有変数を相互に除外し、データの正確性を確保します。共有変数の使用範囲は同じプロセス内です。共有リソースを同時に操作する必要があるプロセスが複数ある場合、どうすれば相互排他的になるのでしょうか?今日のビジネス アプリケーションは通常マイクロサービス アーキテクチャであり、これは 1 つのアプリケーションが複数のプロセスをデプロイすることも意味します。複数のプロセスが MySQL の同じレコード行を変更する必要がある場合、順序の乱れた操作によって引き起こされるダーティ データを避けるために、分散が必要です。今回導入するスタイルはロックされています。ポイントを獲得したい

Springboot はファイルを読み取りますが、jar パッケージにパッケージ化した後、最新の開発にアクセスできません。jar パッケージにパッケージ化した後、Springboot がファイルを読み取れない状況があります。その理由は、パッケージ化後、ファイルの仮想パスが変更されるためです。は無効であり、ストリーム経由でのみアクセスできます。読み取ります。ファイルはリソースの下にあります publicvoidtest(){Listnames=newArrayList();InputStreamReaderread=null;try{ClassPathResourceresource=newClassPathResource("name.txt");Input

SpringBoot と SpringMVC はどちらも Java 開発で一般的に使用されるフレームワークですが、それらの間には明らかな違いがいくつかあります。この記事では、これら 2 つのフレームワークの機能と使用法を調べ、その違いを比較します。まず、SpringBoot について学びましょう。 SpringBoot は、Spring フレームワークに基づいたアプリケーションの作成と展開を簡素化するために、Pivotal チームによって開発されました。スタンドアロンの実行可能ファイルを構築するための高速かつ軽量な方法を提供します。

Springboot+Mybatis-plus が SQL ステートメントを使用して複数テーブルの追加操作を実行しない場合、私が遭遇した問題は、テスト環境で思考をシミュレートすることによって分解されます: パラメーターを含む BrandDTO オブジェクトを作成し、パラメーターをバックグラウンドに渡すことをシミュレートします。 Mybatis-plus で複数テーブルの操作を実行するのは非常に難しいことを理解してください。Mybatis-plus-join などのツールを使用しない場合は、対応する Mapper.xml ファイルを設定し、臭くて長い ResultMap を設定するだけです。対応する SQL ステートメントを記述します。この方法は面倒に見えますが、柔軟性が高く、次のことが可能です。

1. RedisAPI のデフォルトのシリアル化メカニズムである RedisTemplate1.1 をカスタマイズします。API ベースの Redis キャッシュ実装では、データ キャッシュ操作に RedisTemplate テンプレートを使用します。ここで、RedisTemplate クラスを開いて、クラスのソース コード情報を表示します。publicclassRedisTemplateextendsRedisAccessorimplementsRedisOperations、BeanClassLoaderAware{//キーを宣言、値の各種シリアル化メソッド、初期値は空 @NullableprivateRedisSe

プロジェクトでは、構成情報が必要になることがよくありますが、この情報はテスト環境と本番環境で構成が異なる場合があり、実際のビジネス状況に基づいて後で変更する必要がある場合があります。これらの構成をコードにハードコーディングすることはできません。構成ファイルに記述することをお勧めします。たとえば、この情報を application.yml ファイルに書き込むことができます。では、コード内でこのアドレスを取得または使用するにはどうすればよいでしょうか?方法は2つあります。方法 1: @Value アノテーションが付けられた ${key} を介して、構成ファイル (application.yml) 内のキーに対応する値を取得できます。この方法は、マイクロサービスが比較的少ない状況に適しています。方法 2: 実際には、プロジェクト、業務が複雑な場合、ロジック
