Spring Boot SprigAplicationスタートクラス(一)
14518 ワード
目次ディレクトリ クライテリア 、起源 、SpringApple準備段階 2.1、Webアプリケーションタイプを推定する 2.2、アプリケーションコンテキスト初期器を読み込むAppliation Controtext Initializer 2.3、アプリケーションイベントモニタを読み込みます. 2.4、推論アプリケーションガイド 、SpringApple構成 、まとめ 目次
前言
最近はSpring Bootに関する授業を勉強していますが、その過程でメモを取って、便利になったら思い出してください.同時にここで皆さんと検討しています.文章の中に漏れがあったり、補足があったり、間違ったものがあったりしたら、早速提出してください.ここで感謝します.
始まる前に、いくつかの問題を持って勉強してほしいです.2、どうやって実現しましたか?3、長所と短所は何ですか?4、Springとどうやって繋がりましたか?これは自己に対する質問です.問題を持って勉強するのはより良い学習方法であり、理解を深めるのに役立つと思います.はい、これからテーマに入ります.
1、起源
上記の記事では、
注:本記事で使用されているSpring Bootバージョンは2.1.6.BUILD-NAPSHOTです.
2、SprigAplication準備段階
まずスタートクラスを見てみます.
2.1、Webアプリケーションの種類を推定する
Reactive:Reactive応答式プログラミングは、非同期または同時、イベント駆動、プッシュPUSH機構、および観察者モードの派生である新しいプログラミングスタイルです.
2.2、アプリケーションコンテキスト初期器を読み込むApplication Controtext Initializer
次に、Springアプリケーションのコンテキスト初期器をロードするプロセス
例えば、
Application Contect tInitializerインターフェースの主な役割はConfigrable Application Controtext((zhi refsh)メソッドが呼び出す前にいくつかの初期化作業をすることです.
2.3、アプリケーションイベントモニタApplication Listenerをロードする
次いで、アプリケーションイベントモニタ
現在のspring bootでサポートされているイベントの種類は以下の通りです. Apple FailedEvent:このイベントは、spring bootの起動に失敗したときの動作 である. Apple PreparedEvent:コンテキストcontext準備時にトリガ Application ReadyEvent:コンテキストが準備されたときにトリガされる Apple StartEvent:spring boot起動傍受クラス SprigAplication Event:SprigAplicationを取得する Aplication Evironment PreparedEvent:環境事前準備 2.4、推論応用ガイド類
準備段階の最後のステップは、アプリケーションのブートクラスを推定することであり、すなわち、起動main方法のクラスを取得することであり、実行するのは
3、SprigAplicationの配置
4、まとめ
これにより、
以上がこの章の内容です.もし文章の中に間違いがあったり、補充が必要なものがあったら、直ちに提出してください.参考:
『Spring Bootプログラミング思想』
前言
最近はSpring Bootに関する授業を勉強していますが、その過程でメモを取って、便利になったら思い出してください.同時にここで皆さんと検討しています.文章の中に漏れがあったり、補足があったり、間違ったものがあったりしたら、早速提出してください.ここで感謝します.
始まる前に、いくつかの問題を持って勉強してほしいです.2、どうやって実現しましたか?3、長所と短所は何ですか?4、Springとどうやって繋がりましたか?これは自己に対する質問です.問題を持って勉強するのはより良い学習方法であり、理解を深めるのに役立つと思います.はい、これからテーマに入ります.
1、起源
上記の記事では、
Spring Boot
の自動組立に関する知識を説明しましたが、Spring Boot
はどうしてSpringApplication.run()
を実行して起動できるのか分かりません.これはどのようにSpringアプリケーションと文脈を結び、どのようにSpringApplication
を使用してSpringアプリケーションを駆動しますか?次にSpringApplication
についての議論が展開される.注:本記事で使用されているSpring Bootバージョンは2.1.6.BUILD-NAPSHOTです.
2、SprigAplication準備段階
SpringApplication
は、Webアプリケーションタイプを推定し、Springをロードするコンテキスト初期化器やイベントモニター、およびデフォルト属性を設定するなど、動作前に一連の準備を行っている.続いて、ソース方式で勉強します.まずスタートクラスを見てみます.
@SpringBootApplication
public class DiveInSpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(DiveInSpringBootApplication.class, args);
}
}
@SpringBootApplication
この注釈は前の文章で述べたように、自動組立及びスキャンを行うことであり、ここではもはや説明しなく、私達は主にrun方法に注目している.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);
}
primarySources
クラスに入ることによって、SpringApplication
クラスを構成し、その後、run方法を起動することができ、ここで、準備段階の動作はすべてSpringApplication
のコンストラクタで処理されることが分かる.public class SpringApplication {
...
private Set> primarySources;
private WebApplicationType webApplicationType;
private List> initializers;
private List> listeners;
private Class> mainApplicationClass;
public SpringApplication(ResourceLoader resourceLoader, Class>... primarySources) {
// resourceLoader Resource ClassLoader。 null
this.resourceLoader = resourceLoader;
// null,
Assert.notNull(primarySources, "PrimarySources must not be null");
// primarySources SpringApplication.run ,
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// Web
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// initializer
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// listener
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// ,
this.mainApplicationClass = deduceMainApplicationClass();
}
...
}
次に、コンストラクタにおける重点部分について詳細に説明する.2.1、Webアプリケーションの種類を推定する
SpringApplication
は、アプリケーションのタイプを指定することを許可し、Webアプリケーションおよび非Webアプリケーションを実質的に含む.Spring Boot 2.0から始まって、Webアプリケーションはまた Servlet Web
とReactive Web
に分けることができます.準備段階では、現在のClassPath
の下にあるクラスが存在するかどうかを確認することによって、アプリケーションのタイプを導出する.WebApplicationType.deduceFromClasspath()
に入ります.public enum WebApplicationType {
/**
* web
*/
NONE,
/**
* servlet web
*/
SERVLET,
/**
* reactive web
*/
REACTIVE;
private static final String[] SERVLET_INDICATOR_CLASSES = { "javax.servlet.Servlet",
"org.springframework.web.context.ConfigurableWebApplicationContext" };
private static final String WEBMVC_INDICATOR_CLASS = "org.springframework." + "web.servlet.DispatcherServlet";
private static final String WEBFLUX_INDICATOR_CLASS = "org." + "springframework.web.reactive.DispatcherHandler";
private static final String JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer";
private static final String SERVLET_APPLICATION_CONTEXT_CLASS = "org.springframework.web.context.WebApplicationContext";
private static final String REACTIVE_APPLICATION_CONTEXT_CLASS = "org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext";
static WebApplicationType deduceFromClasspath() {
if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
return WebApplicationType.REACTIVE;
}
for (String className : SERVLET_INDICATOR_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
return WebApplicationType.SERVLET;
}
...
}
ClassUtils.isPresent
が存在し、DispatcherHandler
が存在しない場合には、本方法でDispatcherServlet
を用いて判断することができる.ServletContainer
およびReactive web
が存在しない場合、現在のアプリケーションは非Webタイプである.他はServlet
タイプです.Reactive:Reactive応答式プログラミングは、非同期または同時、イベント駆動、プッシュPUSH機構、および観察者モードの派生である新しいプログラミングスタイルです.
2.2、アプリケーションコンテキスト初期器を読み込むApplication Controtext Initializer
次に、Springアプリケーションのコンテキスト初期器をロードするプロセス
ConfigurableWebApplicationContext
に進む.public class SpringApplication {
...
private List> initializers;
public void setInitializers(Collection extends ApplicationContextInitializer>> initializers) {
this.initializers = new ArrayList<>();
this.initializers.addAll(initializers);
}
private Collection getSpringFactoriesInstances(Class type) {
return getSpringFactoriesInstances(type, new Class>[] {});
}
private Collection getSpringFactoriesInstances(Class type, Class>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
// Use names and ensure unique to protect against duplicates
Set names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
}
ここではSpring工場負荷機構Servlet Web
によって取得されることがわかる.上記の記事に関連して説明したように、本方法はsetInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class))
のすべてのリソースからkey SpringFactoriesLoader.loadFactoryNames(type, classLoader)
の実装クラスのセットを取得することであり、以下のようにMETA-INF/spring.factories
のパケットの下のApplicationContextInitializer
ファイルであることを知っている.# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
ここで取得されたのはspring-boot-autoconfigure
およびspring.factories
のコンテキスト初期化器であり、次いでSharedMetadataReaderFactoryContextInitializer
の方法によってこれらの実施形態を初期化する.private List createSpringFactoriesInstances(Class type, Class>[] parameterTypes,
ClassLoader classLoader, Object[] args, Set names) {
List instances = new ArrayList<>(names.size());
for (String name : names) {
try {
Class> instanceClass = ClassUtils.forName(name, classLoader);
Assert.isAssignable(type, instanceClass);
Constructor> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
T instance = (T) BeanUtils.instantiateClass(constructor, args);
instances.add(instance);
}
catch (Throwable ex) {
throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);
}
}
return instances;
}
ここでは、まずConditionEvaluationReportLoggingListener
によってこれらのクラスを初期化し、その後、初期化されたクラスをListに保存して戻ってきて、順序付け動作を行い、最後にcreateSpringFactoriesInstances(type, parameterTypes, classLoader, args, names)
のBeanUtils.instantiate
セットの変数に追加する.これでこのプロセスは終了します.例えば、
SpringApplication
のような初期装置の内容を見てみよう.class SharedMetadataReaderFactoryContextInitializer
implements ApplicationContextInitializer, Ordered {
...
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
applicationContext.addBeanFactoryPostProcessor(new CachingMetadataReaderFactoryPostProcessor());
}
...
}
このクラスは、Springを実装したinitializers
インターフェースと、SharedMetadataReaderFactoryContextInitializer
方法を書き換えることができる.同じように、他のInitializerインターフェースも同様に実現されます.ここでは、コンテキストでApplicationContextInitializer
bean工場のバックプロセッサに加入している.Application Contect tInitializerインターフェースの主な役割はConfigrable Application Controtext((zhi refsh)メソッドが呼び出す前にいくつかの初期化作業をすることです.
2.3、アプリケーションイベントモニタApplication Listenerをロードする
次いで、アプリケーションイベントモニタ
initialize()
をロードし、プロセスは「ローディングアプリケーションコンテキスト初期器」と基本的に一致し、同様にCachingMetadataReaderFactoryPostProcessor
を呼び出す方法であるが、ここで取得されるのは、key setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class))
のオブジェクトセットであり、以下のようにgetSpringFactoriesInstances
のパケットの下のApplicationListener
ファイルである.# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer
最後に、spring-boot-autoconfigure
オブジェクトをspring.factories
方式でBackgroundPreinitializer
属性変数に入れる.public void setListeners(Collection extends ApplicationListener>> listeners) {
this.listeners = new ArrayList<>();
this.listeners.addAll(listeners);
}
私たちも例を挙げて、setListeners
のようなモニターの内容を見てみましょう.public class BackgroundPreinitializer implements ApplicationListener {
...
@Override
public void onApplicationEvent(SpringApplicationEvent event) {
if (!Boolean.getBoolean(IGNORE_BACKGROUNDPREINITIALIZER_PROPERTY_NAME)
&& event instanceof ApplicationStartingEvent && preinitializationStarted.compareAndSet(false, true)) {
...
}
if ((event instanceof ApplicationReadyEvent || event instanceof ApplicationFailedEvent)
&& preinitializationStarted.get()) {
...
}
}
...
}
このクラスは、Springのlisteners
インターフェースを実装し、書き換えBackgroundPreinitializer
方法で対応するイベントをトリガして動作することが分かる.同じように、他のListenerも同様に実現します.このインターフェースの主な機能は、ベリファイア、メッセージ変換器などを含む、他のバックグラウンドスレッドを起動することである.現在のspring bootでサポートされているイベントの種類は以下の通りです.
準備段階の最後のステップは、アプリケーションのブートクラスを推定することであり、すなわち、起動main方法のクラスを取得することであり、実行するのは
ApplicationListener
方法である.private Class> deduceMainApplicationClass() {
try {
StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
for (StackTraceElement stackTraceElement : stackTrace) {
if ("main".equals(stackTraceElement.getMethodName())) {
return Class.forName(stackTraceElement.getClassName());
}
}
}
catch (ClassNotFoundException ex) {
// Swallow and continue
}
return null;
}
onApplicationEvent
方法で現在のスレッドの実行スタックを取得し、deduceMainApplicationClass()
を介して方法名を取得し、main方法かどうかを判断し、最後にmainメソッドの所在クラスに戻ることが見られます.3、SprigAplicationの配置
getStackTrace()
準備段階が終わったら、当然運行段階に入るべきですが、運行段階の前にもう一つの操作があります.つまり、getMethodName()
のデフォルト構成を変更することができます.冒頭のコード例は、アプリケーションのメインクラスのmainメソッドに書かれているのは全部SpringApplication
です.このような書き方は私たちの要求を満たしていないかもしれません.以下は、SpringApplication
を用いて構成を追加する.@SpringBootApplication
public class DiveInSpringBootApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(DiveInSpringBootApplication.class)
//
.web(WebApplicationType.SERVLET)
// banner 、 、 、
.bannerMode(Banner.Mode.OFF)
// banner
.banner()
// initializer
.initializers()
// listeners
.listeners()
.run(args);
}
}
このように実装されたSpringApplication.run(xx.class)
は、カスタム構成を追加することができることが分かる.もちろん配置はこれだけではないです.他のソースも自分で見てください.4、まとめ
これにより、
SpringApplication
の準備作業が終了し、これは主にBanner
、SpringApplicationBuilder
、SpringApplication
、SpringApplication
、primarySources
のこれらの属性を初期化し、webApplicationType
をカスタマイズした構成である.次の記事では、initializers
の動作段階について説明します.これらのlisteners
の構成とアプリケーション初期化器、モニターなどは、どのように使用されていますか?以上がこの章の内容です.もし文章の中に間違いがあったり、補充が必要なものがあったら、直ちに提出してください.参考:
『Spring Bootプログラミング思想』