Baru -baru ini, saya melihat kode sumber musim semi dan tiba -tiba bertanya -tanya bagaimana Spring memulai sendiri tanpa konfigurasi web.xml. Mengingat kemampuan terbatas dan pertama kali saya membaca kode sumber dan memposting blog, maafkan saya jika saya tidak tahu harus berbuat apa ~
Ide yang saya gunakan adalah ide IntelliJ, yang lebih mudah membaca kode sumber daripada myeclipse, dan saya sangat menyukainya di latar belakang hitam. Kemudian proyek dijalankan di bawah plugin Maven Tomcat7. Versi musim semi adalah 4.3.2.release.
Jika Anda telah menulis web pegas dengan konfigurasi anotasi murni, Anda harus tahu bahwa Anda perlu mewarisi kelas inisialisasi untuk memuat kacang, dan kemudian fungsi dan kacang yang disesuaikan akan dimuat dari kelas ini. Di bawah ini adalah salah satu WebInitializer saya
@Order (1) Kelas Publik WebMvCinit memperluas AbstractAnnotationConfigDispatcherServLeTInitializer {kelas terlindungi <?> [] GetRootConfigClasses () {return class baru [] {rootconfig.class, websecurityconfig.class}; } kelas yang dilindungi <?> [] getSerVletConfigClasses () {return class baru [] {webconfig.class}; } string protected [] getservermappings () {return new string [] {"/"}; } @Override Protected Filter [] getSerVletFilters () {return baru filter [] {new HiddenHttpMethodFilter ()}; }}Pertama, lihat struktur kelas AbstractAnnotationConfigDispatcherServletInitializer. Ini juga merupakan fungsi IDEA UML. Diagram klik kanan-> Tampilkan diagram di kelas.
Kemudian kami langsung mengklik AbstractAnnotationConfigDispatcherServletInitializer. Anda dapat melihat bahwa kelas ini sangat sederhana, dengan hanya empat metode. Lalu kami memperhatikan createrootApplicationContext ()
@Override dilindungi WebApplicationContext CreaterOtApplicationContext () {class <?> [] ConfigClasses = getRootConfigClasses (); if (! ObjectUtils.isempty (configClasses)) {annotationConfigWebApplicationContext rootappcontext = new AnnotationConfigWebApplicationContext (); rootappcontext.register (configClasses); return rootappcontext; } else {return null; }}Metode ini secara kasar berarti mendapatkan kelas root yang dikirim oleh pengguna (programmer) dan kemudian mendaftarkan kacang. Ini bukan yang kami khawatirkan, tetapi metode ini harus dieksekusi setelah startup, jadi kami dapat melihat ke atas dari metode ini
Di bawah Ide, Ctrl+G dapat menemukan metode atau kelas untuk dihubungi, dan kemudian mengatur rentang pencarian ke proyek dan perpustakaan
Kami menemukan bahwa metode RegisterContextLoaderListener (ServletContext ServletContext) di bawah AbstractContextLoaderInitializer memanggil CreaterOtApplicationContext () dari Subclass untuk mendapatkan WebApplicationContext, dan lanjutkan untuk menemukan penelepon dari RegisterContextLoTener (ServletContext Layanan) Layanan Context. Akibatnya, ditemukan bahwa itu adalah Onstartup (ServletContext ServletContext) di bawah kelas ini. Kelas AbstractContextLoaderInitializer diposting di bawah ini.
kelas abstrak publik abstrakcontextLoaderInitializer mengimplementasikan WebApplicationInitializer { / ** Logger tersedia untuk subkelas* / Log Log akhir yang dilindungi = logfactory.getLog (getClass ()); @Override public void onStartup (servletContext servletContext) melempar servletException {registerContextLoaderererer (servletContext); } /*** Daftarkan {@link ContextLoaderListener} terhadap konteks servlet yang diberikan. * {@Code ContextLoaderListener} diinisialisasi dengan konteks aplikasi yang dikembalikan * dari metode template {@link #createroTapplicationContext ()}. * @param ServletContext Konteks servlet untuk mendaftarkan pendengar terhadap */ void void yang dilindungi. if (rootAppContext! = null) {contextLoaderRistener listener = new contextLoaderListener (rootAppContext); listener.setContextInitiizers (getRootApplicationContextInitiizers ()); servletcontext.addlistener (pendengar); } else {logger.debug ("No ContextLoaderRistener terdaftar, sebagai" + "createroTapplicationContext () tidak mengembalikan konteks aplikasi"); }} /** * Buat konteks aplikasi "<strong> root </strong>" yang disediakan untuk * {@code ContextLoaderListener}. * <p> Konteks yang dikembalikan didelegasikan ke * {@link ContextLoaderListener#ContextLoaderListener (WebApplicationContext)} dan akan * ditetapkan sebagai konteks induk untuk aplikasi {@code DispatcherServlet} apa pun. Dengan demikian, biasanya berisi layanan tingkat menengah, sumber data, dll. * @Keturn Konteks aplikasi root, atau {@code null} jika konteks root tidak * diinginkan * @see org.springframework.web.servlet.support.abstractdispatcherServLETICEnizer (protected abstracportcextExtlezer *) (protected abstracportcextExt CREREXEXTEXIZER */ Protected Abstraclication AbstracportcextExtExlication; Protected Abstraclication Abstraclication; /** * Tentukan inisialisasi konteks aplikasi yang akan diterapkan pada aplikasi root * konteks bahwa {@code ContextLoaderListener} sedang dibuat. * @since 4.2 * @see #CreaterOtAtApplicationContext () * @See ContextLoaderListener #setContextInitializers */ ApplicationContextInitializer <?> [] getRootApplicationContextInializers () {return null; }}Perhatikan bahwa kami melewatkan kelas abstrak abstrakDispatcherServletInitializer (lihat diagram UML). Kelas ini terutama mengkonfigurasi DispatcherServlet, yang merupakan implementasi Spring MVC dan fungsi lainnya.
Lalu siapa yang akan memuat AbstractContextLoaderInitializer? WebApplicationInitializer sudah menjadi antarmuka, dan tidak akan ada kelas abstrak untuk menyebutnya. Jadi saya mencoba mencari antarmuka WebApplicationInitializer. Karena proyek besar seperti Spring jelas berorientasi antarmuka, panggilan umumnya ditulis ke antarmuka. Kemudian kami menemukan kelas SpringServletContainerInitializer, yang mengimplementasikan antarmuka ServletContainerInitializer. Kelas ini mungkin berarti memulai semua WebApplicationInitiizers. Dapat dikatakan bahwa kelas ini sangat dekat dengan tujuan kami. Di bawah ini adalah SpringservletContainerInitializer
@Handlestypes (WebApplicationInitializer.class) kelas publik SpringservletContainerInitializer mengimplementasikan servletContainerInitializer {@Override public void onStartup (set <? >> WebAppInializerClasses, servletcontext servletContext) LITRETICEKSCEPONECECCECECECCECECECECCECECCECECCECECCECECCECECCECTEXCECCECTEX) LinkedList <SebApplicationInitializer> (); if (webappinitializerclasses! = null) {for (class <?> waiclass: webappinitializerclasses) {// menjadi defensif: beberapa wadah servlet memberi kita kelas yang tidak valid, // apa pun @handlestypes yang dikatakan ... if (! waiclass.isinterface () & & Modifier. WebApplicationInitializer.class.isassignableFrom (waiclass)) {coba {initializers.add ((WebApplicationInitializer) waiclass.newinstance ()); } Catch (Throwable Ex) {Throw New ServletException ("Gagal Instantiate WebApplicationInitializer Class", ex); }}}}} if (initializers.isempty ()) {servletContext.log ("No Spring WebApplicationInitializer Tipe terdeteksi di classPath"); kembali; } servletContext.log (initializers.size () + "Spring WebApplicationInitiizers terdeteksi di classpath"); AnnotationAwareOrdComparator.sort (inisialisasi); untuk (WebApplicationInitializer Initializer: Initializers) {initializer.onstartup (servletContext); }}}Di masa depan terakhir, mulailah semua WebApplicationInitiizers. Jadi pertanyaannya adalah, siapa yang akan memulai SpringservletContainerInitializer? Musim semi pasti tidak akan bisa memulainya dengan sendirinya.
Di lingkungan web, hanya ada wadah web. Kita dapat membuat breakpoint di salah satu tempat di atas dan kemudian men -debug (pada kenyataannya, kita dapat sepenuhnya men -debug = = sepanjang proses, yang akurat dan cepat, tetapi ini tidak memiliki arti pencarian, dan pemandangan di sepanjang jalan cukup bagus)
Anda dapat melihat metode startinternal dari kelas StandardContext di bawah paket org.apache.catalina.core. Ini sudah ada di ruang lingkup Tomcat, jadi tujuan kami telah tercapai. Perhatikan bahwa antarmuka servletContainerInitializer tidak berada di bawah paket pegas, tetapi javax.servlet
Saya kira Tomcat menggunakan antarmuka servletContainerInitializer dari javax.servlet untuk menemukan kelas -kelas yang mengimplementasikan antarmuka ini dalam wadah, kemudian panggil onstartup mereka, dan kemudian SpringServletContaineralizer Springserfule dapat memulai semua WebApplicationInitializer, yang berisi webinitializer yang kami tulis sendiri. Selain itu, Spring Security juga dikonfigurasi dengan anotasi untuk mengimplementasikan WebApplicationInitializer, sehingga Spring sangat dapat diperluas. Mari kita lihat kode sumber Tomcat dalam beberapa hari ke depan untuk memahami mekanisme Tomcat.
Di atas adalah semua konten artikel ini. Saya berharap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.