SpringBoot起動プロセスの浅い分析
1.スタートアップクラス
1.@SpringBootApplicationアノテーション
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
复制代码
自動構成プロセスについては、このブログ投稿を読むことができます
[Spring Boot]SpringBootの自動構成概略図はテキストでいっぱいです-AutumnSunsetBlog-CSDN Blog
2.メインメソッド
public static void main(String[] args) {
SpringApplication.run(AppTest.class, args);
}
复制代码
ファローアップ
最初にメソッド宣言を見てください。静的メソッドはConfigurableApplicationContextインターフェイス実装クラスオブジェクトを返します
実装クラスとサブインターフェイスがたくさんあることがわかります。実装クラスオブジェクトをどのように選択しますか?この質問でソースコードを続けてください。
primarySources //主启动类的class对象
args //main方法的启动参数
复制代码
ここで、新しいSpringApplicationインスタンスが作成され、runメソッドが呼び出されます。
新しいSpringApplication()
新しいSpringApplication(primarySources)メソッドでフォローアップします
public SpringApplication(Class<?>... primarySources) {
this(null, primarySources);
}
复制代码
新しいSpringApplicationインスタンスを作成します。アプリケーションコンテキストは、指定されたプライマリソースからBeanをロードします
工法のフォローアップを続ける
resourceLoader //资源加载器 此时为null
this.resourceLoader = resourceLoader;
复制代码
primarySources //容器中bean的来源 此时为主启动类的字节码对象
复制代码
これは、primarySourcesをnullにすることはできない、または例外がスローされることを表明します
Assert.notNull(primarySources, "PrimarySources must not be null");
复制代码
メソッドパラメーターのprimarySourcesは可変パラメーターであり、primarySourcesはLinkedHashSetに変換されます
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
复制代码
LinkedHashSetセットコレクション要素は、基になるレイヤーを繰り返さないリンクリストであり、整然としたストレージを確保します
次に、このコード行を実行します
this.webApplicationType = WebApplicationType.deduceFromClasspath();
复制代码
このwebApplicationTypeとは何ですか?クリックすると、3つの列挙アイテムを含む列挙であることがわかります。
/**
* The application should not run as a web application and should not start an
* embedded web server.
该应用程序不应作为 Web 应用程序运行,也不应启动嵌入式 Web 服务器。
*/
NONE,
/**
* The application should run as a servlet-based web application and should start an
* embedded servlet web server.
应用程序应作为基于 servlet 的 Web 应用程序运行,并应启动嵌入式 servlet Web 服务器
*/
SERVLET,
/**
* The application should run as a reactive web application and should start an
* embedded reactive web server.
该应用程序应作为响应式 Web 应用程序运行,并应启动嵌入式响应式 Web 服务器
*/
REACTIVE;
复制代码
ここで現在のプロジェクトタイプを判断すると、WebApplicationType.SERVLETが返されます。つまり、現在のSpringApplicationのタイプはWebアプリケーション、組み込みサーブレットWebサーバーです。
次にリスナーを設定します
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
复制代码
次に、プログラムエントリを設定します
this.mainApplicationClass = deduceMainApplicationClass()
复制代码
SpringApplication.run()
次に、runメソッドが何をするか見てみましょう
StopWatch stopWatch = new StopWatch(); //计时器
stopWatch.start(); //开始计时
复制代码
java.awt.headlessというシステムプロパティが設定されています
configureHeadlessProperty()
复制代码
Springアプリケーションコンテキストブートストラップクラスのリスナーを取得し、
SpringApplicationRunListeners listeners = getRunListeners(args)
复制代码
フォローアップして、ApplicationStartingEventイベントを見つけて公開します
listeners.starting();
复制代码
SpringApplicationブートクラスに必要なパラメータをカプセル化します
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args)
复制代码
環境を整える
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
复制代码
現在の環境に基づいて不要なBeanを無視する
configureIgnoreBeanInfo(environment);
复制代码
バナーを印刷
Banner printedBanner = printBanner(environment)
复制代码
ApplicationContextコンテキストを作成する前に、webApplicationTypeのタイプがSERVLETであることを確認してください。
context = createApplicationContext()
复制代码
AnnotationConfigServletWebServerApplicationContextバイトコードオブジェクトを返し、BeanUtils.instantiateClassを呼び出してインスタンス化します
class AnnotationConfigServletWebServerApplicationContext extends ServletWebServerApplicationContext
implements AnnotationConfigRegistry
复制代码
ServletWebServerApplicationContextから継承されます
コンテキストを更新すると、最終的にSpringのrefreshcontainerメソッドが再利用されます
refreshContext(context);
复制代码
ConfigurableApplicationContext.refresh()メソッドを呼び出します
再调用org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#refresh
最後に、org.springframework.context.support.AbstractApplicationContext#refreshを呼び出します
コンテナを更新する12の方法このブログ投稿をチェックしてください
[春]SpringIOCコンテナの起動プロセスと循環依存問題のソースコード分析-AutumnSunsetブログ-CSDNブログ
最後に、タイマーを停止してログを印刷します
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
复制代码