最近、私はSpringのソースコードを見て、突然、Web.xml構成なしでSpringがどのように独自に始まったのか疑問に思いました。限られた能力と初めてソースコードを読んでブログを投稿したことを考えると、何をすべきかわからない場合は許してください〜
私が使用するIDEはIntellijのアイデアであり、MyEclipseよりもソースコードを読みやすく、黒の背景でとても気に入っています。その後、プロジェクトはMaven Tomcat7プラグインの下で実行されます。スプリングバージョンは4.3.2.Releaseです。
純粋なアノテーション構成を備えたスプリングウェブを作成した場合、Beanをロードするために初期化クラスを継承する必要があることを知っておく必要があります。その後、このクラスからカスタマイズされた関数と豆がロードされます。以下は私のウェビナイトサイザーの1つです
@order(1)public class webmvcinit extends abstractannotationconfigdiservletinitializer {protected class <?> [] getrootconfigclasses(){return new class [] {rootconfig.class、websecurityconfig.class}; } protected class <? } protected string [] getServletMappings(){return new String [] {"/"}; } @Override Protected Filter [] getServletFilters(){return new Filter [] {new HiddenHttpMethodfilter()}; }}まず、AbstractAnnotationConfigDisPatcherServletInitializerクラスの構造を見てください。これは、アイデアのUML機能でもあります。右クリック図 - >クラスの図を表示します。
次に、AbstractAnnotationConfigDisPatcherServletInitializerを直接クリックします。このクラスは非常にシンプルで、4つの方法しかないことがわかります。次に、createrootapplicationcontext()に注意を払います
@Override Protected webApplicationContext createrootApplicationContext(){class <?> [] configClasses = getRootConfigClasses(); if(!objectutils.isempty(configclasses)){annotationConfigwebapplicationContext rootappContext = new AnnotationConfigWebApplicationContext(); rootappcontext.register(configclasses); ROUTAPPCONTEXTを返します。 } else {return null; }}この方法は、ユーザー(プログラマー)から送信されたルートクラスを取得し、豆を登録することを大まかに意味します。これらは私たちが心配しているものではありませんが、この方法は起動後に実行する必要があるため、この方法から調べることができます
アイデアの下で、Ctrl+Gは呼び出す方法またはクラスを見つけることができ、プロジェクトとライブラリに検索範囲を設定できます
AbstractContextLoaderInitializerの下のRegisterContextLoaderListener(ServletContext ServletContext)メソッドは、SubclassのCreaterootapplicationContext()を呼び出して、WebApplicationContextを取得し、RegisterContextLoaderListener(サーブレットテキストサーブレットコンテスト)の発信者を見つけ続けることがわかりました。その結果、このクラスの下のonstartup(servletcontext servletcontext)であることがわかります。 AbstractContextLoaderInitializerクラスを以下に掲載します。
パブリッククラスAbstractContextLoaderInitializerを実装するWebApplicationInitializer { / **サブクラスが利用可能* /保護された最終logger = logfactory.getLog(getClass()); @Override public void onstartup(servletcontext servletcontext)servletexception {RegisterContextLoaderListener(servletcontext); } /***特定のサーブレットコンテキストに対してa {@link contextloaderlistener}を登録します。 * {@code ContextLoaderListener}は、{@link #createrootapplicationcontext()}テンプレートメソッドから *返されたアプリケーションコンテキストで初期化されます。 * @param servletcontextサーブレットコンテキストでリスナーを登録する */保護されたvoidcontextloaderlistener(servletcontext servletcontext){webapplicationcontext rootoptext = createrootapplicationcontext(); if(rootappContext!= null){contextLoaderListenerリスナー= new ContextLoaderListener(rootAppContext); listener.setContextInitializers(getRootApplicationContextInitializers()); servletcontext.addlistener(リスナー); } else {logger.debug( "contextloaderlistenerは登録されていません。 }} /** *「<strong> root < /strong>」アプリケーションコンテキストを作成します。 * <p>返されたコンテキストは * {@link ContextLoaderListener#ContextLoaderListener(webApplicationContext)}に委任され、{@code dispatcherservlet}アプリケーション *コンテキストの親コンテキストとして確立されます。そのため、通常、中間層サービス、データソースなどが含まれます。 * @Returnルートアプリケーションコンテキスト、または{@code null}がルートコンテキストが必要でない場合 * @see org.springframework.web.servlet.suptort.suptort.abstractdispatcherservletinitializer */プロテクターのwebアプリケーションCrieTextconttract abst tratt abstatt abst tratt abst tratt abstatt abst tratt crest conttract abst tratt abstration /** * {@code ContextLoaderListener}が作成されているルートアプリケーションに適用されるアプリケーションコンテキスト初期化剤を指定します。 * @since 4.2 * @see #createrootapplicationcontext() * @see contextloaderlistener#setContextInitializers */ protected applicatedContextInitializer <? }}AbstractDispatcherservletinitializer Abstractクラスをスキップしたことに注意してください(UML図を参照)。このクラスは、主にSpring MVCおよびその他の機能の実装であるDispatcherServletを構成します。
では、誰がAbstractContextLoaderInitializerをロードしますか? WebApplicationInitializerはすでにインターフェイスであり、それを呼び出す抽象クラスはありません。そこで、WebApplicationInitializerインターフェイスを検索しようとしました。 Springのような大規模なプロジェクトは間違いなくインターフェイス指向であるため、コールは一般にインターフェイスに書き込まれます。次に、servletcontainerInitializerインターフェイスを実装するSpringservletcontainerInitializerクラスを見つけました。このクラスは、おそらくすべてのWebApplicationInitializersを起動することを意味します。このクラスは私たちの目標に非常に近いと言えます。以下は、springservletcontainerInitializerです
@handlestypes(webapplicationInitializer.class)パブリッククラスSpringservletcontainerInitializerを実装するServletContainerInitializer {@Override public void onstartup(set <class <? linkedlist <webApplicationInitializer>(); if(webappinitializerclasses!= null){for(class <?> waiclass:webappinitializerclasses){//守備:いくつかのサーブレットコンテナは無効なクラスを提供します。 webApplicationInitializer.class.isassignablefrom(waiclass)){try {initializers.add((webapplicationInitializer)waiclass.newinstance()); } catch(throwable ex){新しいservletexception( "WebApplicationInitializerクラスのインスタンス化に失敗しました"、ex); }}}}} if(initializers.isempty()){servletcontext.log( "classPathで検出されたスプリングWebApplicationInitializerタイプはありません");戻る; } servletcontext.log(initializers.size() + "classpathで検出されたspring webapplicationInitializers"); AnnotationAwareOrderComparator.Sort(初期化剤); for(webApplicationInitializer initializer:initializers){initializer.onstartup(servletcontext); }}}最後に、すべてのWebApplicationInitializersを開始します。問題は、SpringservletContainerInitializerを開始するのは誰ですか?春は間違いなくそれだけでそれを始めることができません。
Web環境には、Webコンテナのみがあります。上記の場所のいずれかでブレークポイントを作成してからデバッグできます(実際、プロセス全体で完全にデバッグできます。これは正確かつ高速ですが、これは検索の意味がなく、道路に沿った景色は非常に良いです)
パッケージorg.apache.catalina.coreの下に標準Contextクラスのstartinternalメソッドを見ることができます。これはすでにTomcatの範囲にあるため、私たちの目標は達成されています。 ServletContainerInitializer Interfaceはスプリングパッケージの下ではなく、javax.servletであることに注意してください。
TomcatはJavax.ServletのServletContainerInitializerインターフェイスを使用して、コンテナにこのインターフェイスを実装するクラスを見つけてから、Startupを呼び出し、SpringservletContainerInitializerはすべてのWebApplicationInitializersを開始できます。さらに、Spring Securityは、WebApplicationInitializerを実装するために注釈で構成されているため、Springは非常に拡張可能です。 Tomcatメカニズムを理解するために、今後数日間のTomcatソースコードを見てみましょう。
上記はこの記事のすべての内容です。みんなの学習に役立つことを願っています。誰もがwulin.comをもっとサポートすることを願っています。