Vor kurzem habe ich mir den Quellcode des Frühlings angesehen und sich plötzlich gefragt, wie der Frühling ohne Web.xml -Konfiguration für sich gegründet hat. Angesichts der begrenzten Fähigkeiten und zum ersten Mal, als ich den Quellcode lese und einen Blog veröffentlichte, verzeihen Sie mir bitte, ob ich nicht weiß, was ich tun soll ~
Die IDE, die ich benutze, ist Intellij IDEA, die den Quellcode leichter zu lesen ist als MyeClipse, und ich mag es sehr im schwarzen Hintergrund. Dann wird das Projekt unter Maven Tomcat7 Plugin ausgeführt. Die Frühlingsversion ist 4.3.2.Release.
Wenn Sie ein Spring -Web mit reiner Annotationskonfiguration geschrieben haben, sollten Sie wissen, dass Sie eine Initialisierungsklasse erben müssen, um die Bohne zu laden, und dann werden unsere individuellen Funktionen und Bohnen aus dieser Klasse geladen. Unten ist einer meiner Webinitialisatoren
@Order (1) public class webmvcinit erweitert AbstractAnnotationConFigDispatcherServletInitializer {Protected Class <?> [] GetRootConfigClasses () {neue Klasse zurückgeben [] {rootconfig.class, WebSecurityConfig.class}; } Protected Class <?> [] getServletConfigclasses () {neue Klasse zurückgeben [] {webconfig.class}; } protected String [] getServletMappings () {return New String [] {"/"}; } @Override Protected Filter [] getServletFilters () {neuer Filter zurückgeben [] {new HiddenhttpMethodFilter ()}; }}Schauen Sie sich zunächst die Struktur der AbstractAnnotationConfigDispatcherServletinitializer -Klasse an. Dies ist auch eine UML -Funktion der Idee. Klicken Sie mit der rechten Maustaste auf Diagramme-> Diagramme in der Klasse.
Anschließend klicken wir direkt auf AbstractAnnotationConfigDispatcherServletinitializer. Sie können sehen, dass diese Klasse mit nur vier Methoden sehr einfach ist. Dann achten wir auf CreaterootApplicationContext ()
@Override Protected WebApplicationContext CreaterootApplicationContext () {class <?> [] Configclasses = getRootConfigClasses (); if (! ObjectUtils.isempty (configClasses)) {AnnotationConfigWebApplicationContext RootAppContext = new AnnotationConfigWebApplicationContext (); rootAppContext.register (configclasses); return rootAppContext; } else {return null; }}Diese Methode bedeutet grob, die vom Benutzer (Programmierer) gesendeten Stammklassen zu erhalten und dann die Bohnen zu registrieren. Dies sind nicht das, worüber wir uns Sorgen machen, aber diese Methode sollte nach dem Start ausgeführt werden, sodass wir von dieser Methode nachsehen können
Unter der Idee kann Strg+G eine Methode oder Klasse finden, die Sie anrufen können, und dann den Suchbereich auf Projekt und Bibliothek festlegen
Wir fanden heraus, dass die RegisterContextLaDerListener -Methode (ServletContext ServletContext) unter AbstractContextInInitializer den CreaterootApplicationContext () der Unterklasse aufruft, um die WebApplicationContext -Methode zu erhalten, und weiterhin die Anrufer der RegisterContextListener (servletContextContext) -Methode zu finden. Infolgedessen ist festgestellt, dass es sich um den OnStartup (ServletContext ServletContext) unter dieser Klasse handelt. Die AbstractContextloaderInitializer -Klasse ist unten veröffentlicht.
public Abstract Class AbstractContextoLaderInitializer implementiert WebApplicationInitializer { / ** Logger, die für Unterklassen verfügbar sind @Override public void onStartup (servletContext servletContext) löst ServletException {RegisterContextLoaderListener (ServletContext) aus; } /*** Registrieren Sie einen {@link contextloaderListener} gegen den angegebenen Servlet -Kontext. Der * {@Code contextloaderListener} wird mit dem Anwendungskontext initialisiert, der * aus der Templatmethode {@link #createrApplicationContext ()} zurückgegeben wurde. * @param servletContext Der Servlet -Kontext, der den Hörer gegen */ Protected void RegisterContextLaListener (ServletContext ServletContext) registriert hat, {WebApplicationContext RootAppContext = CreaterootApplicationContext (); if (rootAppContext! listener.setContextInitializer (getrootApplicationContextInitializer ()); servletContext.addListener (Hörer); } else {logger.debug ("no contextloaderListener registriert, als" + "createrootApplicationContext () gab keinen Anwendungskontext zurück"); }} /** * Erstellen Sie den Anwendungskontext "<strong> root < /strong>", der dem * {@Code contextloaderListener} angegeben werden soll. * <P> Der zurückgegebene Kontext wird an * {@link contextloaderListener#contextloaderListener (WebApplicationContext)} delegiert und wird als übergeordneter Kontext für jeden {@Code -DispatcherServlet} -Antrag * Kontext eingerichtet. Daher enthält es typischerweise Middle-Tier-Dienste, Datenquellen usw. * @return den Root-Anwendungskontext oder {@Code null}, wenn ein Root-Kontext nicht * @see org.springFramework.web.Servlet.Support.AbstractDispatcherServletinitializer */ Protected creveroptcluktionalizer (proteded crescrected crotected cressited cressitected crescrected crectract () webaplicationcontext () webaplicationcontext (); /** * Geben Sie den Anwendungskontext -Initialisierer an, um auf den Root -Anwendung * Kontext anzuwenden, mit dem {@code contextloaderListener} erstellt wird. * @Since 4.2 * @see #CreateroTapplicationContext () * @see contextloaderListener #setContextInitializer */ Protected ApplicationContextInitializer <?> [] GetRootApplicationContextInitializer () {return null; }}Beachten Sie, dass wir die AbstractDispatcherServletinitializer -Abstract -Klasse übersprungen haben (siehe UML -Diagramm). Diese Klasse konfiguriert hauptsächlich Dispatcherservlet, die Implementierung von Spring MVC und anderen Funktionen.
Wer lädt dann den AbstractContextloaderInitializer? WebApplicationInitializer ist bereits eine Schnittstelle, und es gibt keine abstrakte Klasse, die sie aufrufen kann. Deshalb habe ich versucht, die WebanapplicationInitializer -Schnittstelle zu durchsuchen. Da große Projekte wie Spring definitiv interface orientiert sind, wird der Anruf im Allgemeinen an die Schnittstelle geschrieben. Anschließend fanden wir die SpringServletContainerInitializer -Klasse, die die ServletContainerInitializer -Schnittstelle implementiert. Diese Klasse bedeutet wahrscheinlich, dass alle WebanapplicationInitializer gründen. Es kann gesagt werden, dass diese Klasse unserem Ziel sehr nahe ist. Unten finden Sie den SpringServletContainerInitializer
@HandLestypes (WebApplicationInitializer.Class) öffentliche Klasse SpringServletContainerInitializer implementiert servletContainerInitializer {@Override public void onStartup (set <class <>> webappinitializerclasses, servletContextcontext -servletContext). LinkedList <NEWAPlicationInitializer> (); if (webAppinitializerclasses! WebApplicationInitializer.class.IsSignableFrom (Waiclass)) {try {initializer.add ((WebApplicationInitializer) Waiclass.Newinstance ()); } catch (Throwable Ex) {neue servleTexception ("" WebApplicationInitializer -Klasse nicht instanziiert ", Ex); }}}}} if (initializer.isempty ()) {servletContext.log ("No Spring WebApplicationInitializer -Typen, die auf ClassPath erkannt wurden"); zurückkehren; } servletContext.log (initializer.size () + "Spring WebApplicationInitializer auf Klassenpfad"); AnnotationAwareOrderComparator.sort (Initialisierer); für (WebApplicationInitializer Initializer: Initializer) {initializer.onstartup (ServletContext); }}}Starten Sie im letzten Vorgang alle WebapplicationInitializer. Die Frage ist also, wer wird SpringServletContainerInitializer anfangen? Der Frühling wird definitiv nicht in der Lage sein, es alleine zu starten.
In der Webumgebung gibt es nur Webcontainer. Wir können an einem der oben genannten Orte einen Haltepunkt erstellen und ihn dann debuggen (in der Tat können wir während des gesamten Prozesses vollständig debuggen, was genau und schnell ist, aber dies fehlt die Bedeutung der Suche, und die Landschaft entlang der Straße ist ziemlich gut)
Sie können die Startinterne Methode der Standardcontext -Klasse unter dem Paket org.apache.catalina.core sehen. Dies liegt bereits im Rahmen von Tomcat, daher wurde unser Ziel erreicht. Beachten Sie, dass die ServletContainerInitializer -Schnittstelle nicht unter dem Federpaket ist, sondern javax.servlet ist
Ich denke, dass Tomcat die ServletContainerInitializer -Schnittstelle von Javax.servlet verwendet, um die Klassen zu finden, die diese Schnittstelle im Container implementieren, und dann ihre OnStartups aufrufen, und dann kann SpringServletContaineritializer von Spring, das die Webinitializer, die wir selbst haben, beginnen können. Darüber hinaus ist die Spring Security auch mit Annotation konfiguriert, um WebApplicationInitializer zu implementieren, sodass die Feder sehr erweiterbar ist. Schauen wir uns den Tomcat -Quellcode in den nächsten Tagen an, um den Tomcat -Mechanismus zu verstehen.
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, es wird für das Lernen aller hilfreich sein und ich hoffe, jeder wird Wulin.com mehr unterstützen.