序文
この記事では、主に、Spring Bootのサーブレットスタートアッププロセスと原則に関する関連コンテンツを紹介します。以下ではあまり言いません。詳細な紹介を一緒に見てみましょう。
スタートアッププロセスと原則:
1スプリングブートアプリケーションスタートアップ実行方法
STOPWATCH STOPWATCH = new StopWatch(); stopwatch.start(); configureableapplicationContext context = null; FailureAnalyzers Analyzers = null; configureheadlessproperty(); SpringApplicationRunListenersリスナー= getRunListeners(args); listens.starting(); try {applicationArguments applicationArguments = new DefaultApplicationArguments(args); configureableenvironment環境= prepareenvironment(リスナー、アプリケーションアールグ); Banner printedbanner = printbanner(環境); // ApplicationContext Contenter Context = createapplicationContext();を作成します。アナライザー=新しいFailureAnalyzers(コンテキスト); prepereContext(コンテキスト、環境、リスナー、アプリケーションアルグ、印刷砲); // IOC Container refreshContext(context); AfterRefresh(Context、ApplicationArguments);リスナー。フィニッシュ(コンテキスト、null); stopwatch.stop(); if(this.logstartupinfo){new StartupInfologger(this.mainApplicationClass).logstarted(getApplicationLog()、sopwatch); } return Context; } catch(throwable ex){handlerunfailure(コンテキスト、リスナー、アナライザー、ex);新しいIllegalStateException(Ex); }2 createapplicationContext():IOCコンテナを作成します。 Webアプリケーションの場合は、AnnotationConfigembedDedWebApplicationのIOCコンテナを作成します。そうでない場合は、AnnotationConfigApplicationのIOCコンテナを作成します。
public static final string default_context_class = "org.springframework.context。" + "annotation.annotationConfigApplicationContext"; /** * Web *環境にデフォルトで使用されるアプリケーションコンテキストのクラス名。 */ public static final string default_web_context_class = "org.springframework。" + "boot.context.embedded.annotationconfigemdedwebapplicationContext"; protected configurableapplicationContext createapplicationContext(){class <?> contextClass = this.ApplicationContextClass; if(contextclass == null){try {//アプリケーション環境Contextclass = class.forname(this.webenvironment?default_web_context_class:default_context_class); } catch(classNotFoundException ex){新しいIllegalStateExceptionをスロー( "デフォルトのApplicationContextを作成できません" + "ApplicationContextClass"を指定してください "、ex); }} return(configureableapplicationContext)beanutils.instantiate(contextclass); }3 REFRESHCONTEXT(コンテキスト)Spring BootはIOCコンテナを再リッシュします(コンテナオブジェクトを作成し、コンテナの初期化し、コンテナの各コンポーネントを作成します)
private void refreshContext(configureableapplicationContext Context){refresh(context); if(this.registershutdownhook){try {context.registershutdownhook(); } catch(AccessControlexception ex){//一部の環境では許可されていません。 }}}}4 REFRESH(コンテキスト);作成したばかりのIOCコンテナを更新します
Protected void refresh(applicationContext ApplicationContext){assert.isinstanceof(abstractApplicationContext.class、applicationContext); ((AbstractApplicationContext)ApplicationContext).Refresh(); }5。親クラスの更新()メソッドを呼び出します
public void refresh()Throws BeanSexception、IllegalStateException {object var1 = this.startupshutdownmonitor;同期(this.startupshutdownmonitor){this.preparerefresh(); configurablelistablebeanfactory beanfactory = this.obtainfreshbeanfactory(); this.preparebeanfactory(beanfactory); try {this.postprocessbeanfactory(beanfactory); this.invokebeanfactorypostprocessors(beanfactory); this.registerbeanpostprocessors(beanfactory); this.InitmessageSource(); this.InitApplicationEventMulticaster(); this.onrefresh(); this.registerListeners(); this.finishbeanfactoryInitialization(beanfactory); this.finishrefresh(); } catch(beansexception var9){if(this.logger.iswarnenabled()){this.logger.warn( "コンテキスト初期化中に遭遇した例外 - 更新試行のキャンセル:" + var9); } this.destroybeans(); this.cancelrefresh(var9); var9を投げる; }最後に{this.resetcommoncaches(); }}}6サブクラスのonrefreshメソッドebdedwebapplicationcontextの抽象的親クラスabstractapplicationcontext
@Override Protected void onrefresh(){super.onrefresh(); try {createembeddedservletcontainer(); } catch(throwable ex){新しいapplicationContextException( "埋め込みコンテナを起動できない"、ex); }}7 createembededservletcontainerでは、埋め込まれたサーブレットコンテナ工場が取得され、サーブレットはコンテナファクトリーから作成されます
private void createembeddedservletcontainer(){embeddedservletcontainer localcontainer = this.embededservletcontainer; servletContext localservletcontext = getservletcontext(); if(localcontainer == null && localservletcontext == null){//埋め込まれたサーブレットコンテナファクトリー埋め込み型埋め込み型コントコントカンテンファクトリー= getembededservletcontainerfactory(); //コンテナ工場に基づいて対応する埋め込みサーブレットコンテナを取得します。 } else if(localservletcontext!= null){try {get selfinitializer()。onstartup(localservletcontext); } catch(servletexception ex){new ApplicationContextException( "Servlet Contextを初期化できない"、ex); }} initPropertySources(); }8 IOCコンテナからサーブレットコンテナファクトリーを入手します
// EmbedDedWebApplicationContext#GetemBededServletContainerFactory EmbedDedServletContainerFactory GetemdedServletContainerFactory(){// Bean Nameを使用して、階層文字列[] BeanNames = GetBeanFactory()を考慮しないようにしています。 .getBeanNamesFortype(EmbedDedServletContainerFactory.Class); if(beannames.length == 0){new ApplicationContextExceptionをスロー( "欠落しているためにembedDedWebApplicationContextを開始できない" + "embeddedServletContainerContoryFactory Bean。"); } if(beannames.length> 1){new applicationContextException( "複数の" + "embeddedservletcontainerfactory beans:" + stringutils.arraytocommadelimettring(beannames))のためにembeddedwebapplicationContextを開始できません(beannames)); } return getBeanFactory()。getBean(beannames [0]、embeddedservletcontainerfactory.class); }9サーブレットコンテナ工場を使用して、埋め込みサーブレット容器を取得します。使用するコンテナ工場は、構成環境依存度によって異なります
this.embededservletcontainer = containerfactory .getembededservletcontainer(get selfinitializer());
10上記の作成プロセスでは、最初にIOCコンテナを起動し、次に埋め込まれたサーブレットコンテナを起動し、次に自分で作成したコントローラーなど、IOCコンテナで作成されていない残りのオブジェクトを取得します。
//残りのすべての(怠lazyinit)シングルトンをすべてインスタンス化します。 FinishBeanFactoryInitialization(BeanFactory);
保護されたvoid finishbeanfactoryInitialization(configureablelistablebeanfactory beanfactory){//このコンテキストの変換サービスを初期化します。 if(beanfactory.containsbean(conversion_service_bean_name)&& beanfactory.istypematch(conversion_service_bean_name、conventionservice.class)){beanfactory.setConversionservice(beanfactory.getBean_service_service_bean_name、convensionervice.class); } //デフォルトの埋め込み値リゾルバーを登録してください。 if(!beanfactory.hasembeddedvalueresolver()){beanfactory.addembeddedvalueresolver(new StringValueresolver(){@Override public String ResolveStringValue(String Strval){return getEnvironment()。ResolvePlaceHolders(); strval);}}); } // loadtimeweaverawareの豆を早期に初期化して、トランスを早期に登録できるようにします。 string [] weaverawarenames = beanfactory.getbeannamesfortype(loadtimeweaveraware.class、false、false); for(string weaverawarename:weaverawarenames){getbean(weaverawarename); } //タイプマッチングに一時クラスローダーの使用を停止します。 beanfactory.settempclassloader(null); //さらなる変更を期待せずに、すべてのBean定義メタデータをキャッシュすることを許可します。 beanfactory.freezeconfiguration(); //残りのすべての(怠lazyinit)シングルトンをすべてインスタンス化します。 BeanFactory.PreinStantiateSingletons(); }PreintantiateSinglettonsメソッドをご覧ください
public void preinstantiateSingletons()はBeanSexceptionを投げます{if(this.logger.isdebugenabled()){this.logger.debug( "" + this); } list <string> beanNames = new ArrayList(this.beanDefinitionNames); Iterator var2 = beannames.iterator(); while(true){while(true){string beanname; rootbeandefinition bd; do {do {do {if(!var2.hasnext()){var2 = beannames.iterator(); while(var2.hasnext()){beanname =(string)var2.next();オブジェクトSingleTonInstance = this.getSingleton(beanname); if(singletonInstance of SmartInitializingingingleton){final SmartInitializingingLeton SmartSingleton =(SmartInitializingingSingleton)SingleTonInstance; if(system.getSecurityManager()!= null){AccessController.Doprivileded(new Priviledaction <Object>(){public object run(){smartsingleton.aftersingletonsinsintantided(); return null;}}、this.getaccesstrolcontext(); } else {smartsingleton.aftersingletonsinStantided(); } } 戻る; } beanname =(string)var2.next(); bd = this.getmergedlocalbeandefinition(beanname); } while(bd.isabstract()); } while(!bd.issingleton()); } while(bd.islazyinit()); if(this.isfactorybean(beanname)){final factorybean <?> factory =(factorybean)this.getbean( "&" + beanname); Boolean iseagerinit; if(system.getSecurityManager()!= null && smartfactorybean){iseagerinit =((boolean)accesscontroller.dopriviledeged(new boolean run>(){public boolean run(){return((smartfactorybean)factory)。 this.getAccessControlContext()))。booleanValue(); } else {iseagerinit = smartfactorybean &&((smartfactorybean)factory).iseagerinit(); } if(iseagerinit){this.getbean(beanname); }} else {// register bean this.getBean(beanname); }}}}}}}}}}}GetBeanメソッドを使用して、反射を通じてすべての未作成のインスタンスを作成します。
組み込みサーブレットコンテナの使用:
利点:シンプルでポータブル
短所:JSPはデフォルトではサポートされていません、最適化とカスタマイズはより複雑です
外部サーブレットコンテナを使用する手順:
1.戦争プロジェクトを作成する必要があり、Jianhao Webプロジェクトのディレクトリ構造が必要です。
2埋め込まれたTomcat依存性範囲が指定されています
3 Springbootservletinitializerクラスのサブクラスを書いて、構成メソッドをオーバーライドします
パブリッククラスServletInitializerは、SpringBootservletInitializer {@Override Protected SpringApplicationBuilder Configure(SpringApplicationBuilder Application){return application.Sources(SpringBoot04WebjSpapplication.class); }}4サーバーを起動します
開始JARパッケージとWARパッケージの違い
JARパッケージ:SpringBootApplicationの実行方法を実行し、IOCコンテナを起動してから、埋め込みサーブレットコンテナを作成します
戦争パッケージ:最初に、サーブレットサーバーを起動し、サーバーはSpringbootアプリケーション(Springbootservletinitizer)を起動し、IOCコンテナを起動します
サーブレット3.0+ルール
1。ServerStartup(Webアプリケーションスタートアップ)、現在のWebアプリケーションのすべてのJARパッケージのServletContainerlnitializerインスタンスが作成されます。
2 ServletContainerInitializerの実装は、JARパッケージのMeta-INF/Servicesフォルダーに配置されています
3 @handlestypes annotationを使用して、アプリケーションの開始時に指定されたクラスをロードすることもできます。
外部Tomcatプロセスと原則
tomcatを開始します
spring上記のサーブレット3.0+ルールによると、javax.servlet.servletcontainerInitializerという名前のファイルをSpring Webモジュールに見つけることができ、ファイルのコンテンツはorg.springframework.web.springservletcontainerinitializerです。
springservletcontainerInitializerの定義を見てください
@handlestypes(webapplicationInitializer.class)パブリッククラスSpringservletContainerInitializerを実装しているServletContainerInitializer { /** * {@code servletcontext}を、アプリケーションのクラスに存在する実装を{@link webapplicationInitializer} * * <p>Because this class declares @{@code HandlesTypes(WebApplicationInitializer.class)}, * Servlet 3.0+ containers will automatically scan the classpath for implementations * of Spring's {@code WebApplicationInitializer} interface and provide the set of all * such types to the {@code webAppInitializerClasses} parameter of this method. * <p> {@code webApplicationInitializer}の実装がclassPathにある場合、 *この方法は事実上無作法です。 {@code servletcontainerinitializer}が実際に呼び出されたことをユーザーに通知する情報レベルのログメッセージが発行されますが、 * no {@code webapplicationInitializer}の実装が見つかりました。 * <p> 1つ以上の{@code webapplicationInitializer}タイプが検出されると仮定して、 *@{@link.springframework.core.annotation.Order @Order}の@{@link.springframework.core.Order @Order}の場合、それらはインスタンス化されます(および<em> sorted </em>。次に、{@link webapplicationInitializer#onstartup(servletcontext)} *メソッドが各インスタンスで呼び出され、{@code servletcontext}を委任します *各インスタンスは、springの * {@code dispatcherervlet}、springの文脈{@code dispatcherservletなどのリスナーなどのサワードを登録および構成することができます。フィルターなどのコンポーネント。 onstartup(set <class <? //防御:一部のサーブレットコンテナは無効なクラスを提供します。コレクションInitializers.Add((webApplicationInitializer)waiclass.newinstance())} {スロー可能){"WebApplicationInitializerクラスをインスタンス化しなかった"、ex}}} classpathで検出されたタイプ "); return;} servletcontext.log(initializers.size() +" classPathで検出されたスプリングwebApplicationInitializers "); annotationAwareOrderComparator.sort(初期化者); InitialIzer.ONSTARTUP(servletcontext);上記の長いコメントでは、springservletcontainerInitializerが@handlestypes(webapplicationInitializer.class)によって注釈が付けられたWebApplicationInitializerタイプのすべてのクラスをOnstartupメソッドの設定パラメーターに渡し、これらのwebApplicationInitializerタイプのインスタンスを反映して作成することがわかります。
④メソッドの最後に、各webApplicationInitilizerの実装は独自のon -startupメソッドを呼び出します
⑤WebApplicationInitializerには、抽象的な実装クラスSpringBootservletInitializer(この抽象クラスを継承したことを覚えておいてください)があり、各WebApplicationInitializerインスタンス(SpringBootservletinitializerを含む)のスタートアップ方法が呼び出されます。
パブリッククラスSpringbootservletinitializerを実装したWebApplicationInitializer {//その他のコード... @Override public void onstartup(servletcontext servletcontext)servletexception {//ロガーの初期化は、順序付けられた// logservletcontextinitializerが使用されています。 // IOCコンテナWebApplicationContext rootappContext = createrootApplicationContext(servletContext); if(rootappcontext!= null){servletcontext.addlistener(new ContextLoaderListener(rootappContext){@OverRide public void contextInitialized(servletContexteventイベント){//アプリケーションコンテキストがすでに初期化されているため}}); } else {this.logger.debug( "createrootapplicationcontext()が" + "not" + "アプリケーションコンテキスト"を返しませんでした。 }} protected webApplicationContext createrootapplicationContext(servletContext servletContext){//スプリングアプリケーションビルダーを作成し、関連するプロパティSpringApplicationBuilder Builder = createSpringApplicationBuilder(); stardentservletenvironment環境=新しいStardnardServletenvironment(); Environment.InitPropertySources(servletcontext、null); Builder.Environment(環境); builder.main(getClass()); ApplicationContext parent = getExistingRootWebApplicationContext(servletContext); if(parent!= null){this.logger.info( "rootコンテキストが既に作成されている(親として使用して)。"); servletcontext.setattribute(webapplicationcontext.root_web_application_context_attribute、null); Builder.Initializers(new ParentContextApplicationContextInitializer(親)); } builder.Initializers(new ServletContextApplicationContextInitializer(servletcontext)); builder.contextclass(annotationConfigembeddedwebapplicationContext.class); // SpringBootservletInitializerのサブクラスが構成メソッドをオーバーライドするため、定義したサブクラスによってオーバーライドされた構成メソッドがここで呼び出されるため、Configureメソッドを呼び出してWARタイプのWebプロジェクトを作成した後。 Builder = configure(builder); //スプリングアプリケーションはビルダーを介して構築されます。 SpringApplication Application = builder.build(); if(application.getSources()。isempty()&& annotationutils .findannotation(getclass()、configuration.class)!= null){application.getSources()。add(getClass()); } assert.state(!application.getSources()。isempty()、 "SpringApplicationソースは定義されていません。 //エラーページが登録されていることを確認してください} //スプリングアプリケーションを起動するreturn run(application); } //スプリングアプリケーションは、IOCコンテナ保護されたwebApplicationContext run(springApplication Application){return(webApplicationContext)application.run(); }}SpringBootservletInitializerインスタンスがOnStartupメソッドを実行すると、実行方法はCreaterootApplicationContextメソッドを介して実行されます。次のプロセスは、JARパッケージの形で開始されたアプリケーションの実行プロセスと同じです。 IOCコンテナは内部で作成され、返されます。ただし、WARパッケージの形式でのアプリケーションは、IOCコンテナの作成プロセス中にサーブレットコンテナを作成しなくなります。
要約します
上記は、この記事のコンテンツ全体です。この記事の内容には、すべての人の研究や仕事に特定の参照値があることを願っています。ご質問がある場合は、メッセージを残してコミュニケーションをとることができます。 wulin.comへのご支援ありがとうございます。