Vorwort
In diesem Artikel wird hauptsächlich die relevanten Inhalte über den Servlet -Startprozess und die Prinzipien im Spring Boot vorgestellt. Ich werde unten nicht viel sagen. Schauen wir uns die detaillierte Einführung zusammen an.
Startup -Prozess und Prinzipien:
1 Feder -Boot -Anwendungsstart -Start -Ausführungsmethode
STOPWATCH STOPWATCH = NEW STOPWATCH (); stopwatch.start (); ConfigurableApplicationContext context = null; Failureanalyzers Analyzer = NULL; configureHeadlessProperty (); SpringApplicationRunListeners Hörer = getrunListeners (Args); Hörer.Starting (); try {applicationArgumente applicationArgumente = new DefaultApplicationArgumente (Args); Umgebung für Konfigurieren von Umgebung = Vorbereitungsumgebung (Hörer, applicationArgumente); Banner PrintEdBanner = PrintBannerer (Umgebung); // Erstellen Sie einen applicationContext container context = createApplicationContext (); Analysatoren = neue Failureanalysatoren (Kontext); PrepareContext (Kontext, Umgebung, Hörer, applicationArguments, PrintedBanner); // IOC -Container -RefreshContext (Kontext) aktualisieren; AfterRefresh (Kontext, applicationArgumente); Hörer. stopwatch.stop (); if (this.logstartupinfo) {New StartUpInfologger (this.mainApplicationClass) .LogStarted (getApplicationog (), Stoppwatch); } Rückgabekontext; } catch (throwable ex) {HandlerunFailure (Kontext, Zuhörer, Analysatoren, Ex); neue IllegalStateException (Ex) werfen; }2 CreateApplicationContext (): Erstellen Sie einen IOC -Container. Wenn es sich um eine Webanwendung handelt, erstellen Sie einen IOC -Container mit AnnotationConFigembededWebApplication. Wenn dies nicht der Fall ist, erstellen Sie einen IOC -Container mit AnnotationConfigapplication.
public static Final String default_context_class = "org.springframework.context." + "Annotation.AnnotationConfigapplicationContext"; /** * Der Klassenname des Anwendungskontexts, der standardmäßig für Web * -Enumgebungen verwendet wird. */ public static Final String default_web_context_class = "org.springframework." + "boot.context.embedded.annotationConFigembeddedWebApplicationContext"; Protected ConfigurableApplicationContext createApplicationContext () {class <?> contextclass = this.applicationContextClass; if (contextclass == null) {try {// verschiedene IOC -Container gemäß der Anwendungsumgebung contextclass = class.forname (this.webenvironment? default_web_context_class: default_context_class); } catch (classNotFoundException ex) {neue IllegalStateException werfen ("Ein Standard -ApplicationContext nicht erstellen," + "Bitte eine applicationContextClass angeben", ex); }} return (configurableApplicationContext) beanutils.instantiate (contextClass); }3 RefreshContext (Kontext) Spring -Start aktualisiert den IOC -Container (erstellen Sie Containerobjekte, initialisieren Sie den Container und erstellen Sie jede Komponente des Containers).
private void RefreshContext (configurableApplicationContext -Kontext) {reproshs (context); if (this.registerShutDownhook) {try {context.registerShutDownhook (); } catch (AccessControlException ex) {// in einigen Umgebungen nicht zulässig. }}}}4 Aktualisieren (Kontext); Aktualisieren Sie den gerade erstellten IOC -Behälter
Protected void Refresh (applicationContext applicationContext) {assert.issinstanceof (AbstractApplicationContext.class, ApplicationContext); ((AbstractApplicationContext) applicationContext) .refresh (); }5. Rufen Sie die Methode der Elternklasse refresh () auf
public void refresh () wirft Beansexception aus, illegalStateException {Object var1 = this.startUpShutdownMonitor; synchronisiert (this.StartUpShutdownMonitor) {this.preperReReFresh (); ConfigurablelistableBeArtory 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 ("Ausnahme während der Kontextinitialisierung - Abbrechen Aktualisierung Versuch:" + var9); } this.destroybeans (); this.cancelrefresh (var9); Var9 werfen; } endlich {this.resetcommoncaches (); }}}Sech
@Override protected void onrefresh () {super.onrefresh (); probieren {createMbeddedServletContainer (); } catch (throwable ex) {town applicationContextexception ("Eingebetteter Container nicht starten", Ex); }}7 Im CreateMbeddedServletContainer wird die eingebettete Servlet -Containerfabrik erhalten, und das Servlet wird aus der Containerfabrik erstellt
private void createMbeddedServletContainer () {EmbeddedServletContainer localContainer = this.embededdeServletContainer; ServletContext LocalServletContext = getServletContext (); if (localContainer == null && localServletContext == null) {// eingebettete Servlet -Container -Fabrik eingebettetem servletServletContainerFactory ContainerFactory = getembeddedServletContainerFactory (); // Erhalten Sie den entsprechenden eingebetteten Servlet -Container basierend auf der Containerfabrik. } else if (localServletContext! } catch (servleTexception ex) {thrower New ApplicationContexception ("" Servlet -Kontext kann nicht initialisieren ", Ex); }} initpropertySources (); }8 Holen Sie sich Servlet Container Factory aus dem IOC -Container
//EmbeddedWebApplicationContext#getEmbeddedServletContainerFactory protected EmbeddedServletContainerFactory getEmbeddedServletContainerFactory() { // Use bean names so that we don't consider the hierarchy String[] beanNames = getBeanFactory() .GetBeannamesForForType (EmbeddedServletContainerFactory.class); if (beannames.length == 0) {throw New ApplicationContexception ("EingebettetwebApplicationContext kann aufgrund fehlender" + "embeddedServletContainerFactory Bean nicht gestartet werden."); } if (beannames.length> 1) {town applicationContexception werfen ("EingebettetwebApplicationContext kann aufgrund mehrerer" + "eingebettetServletContainerFactory Beans:" + StringUtils.ArrayTocommaMmadelimitedString (BEANNAMES)); } return getBeanFactory (). getBean (Beannames [0], EmbeddedServletContainerFactory.class); }9 Verwenden Sie die Servlet -Containerfabrik, um eingebettete Servletbehälter zu erhalten. Welche zu verwendende Containerfabrik abhängt, hängt von der Konfigurationsumgebungsabhängigkeit ab
this.embeddedServletContainer = ContainerFactory .GetembeddedServletContainer (GetSelfInitializer ());
10 Der obige Erstellungsprozess startet zuerst den IOC -Container, startet dann den eingebetteten Servlet -Container und ruft dann die verbleibenden Objekte ab, die nicht im IOC -Container erstellt wurden, z. B. den von Ihnen erstellten Controller.
// alle verbleibenden (nicht-lazy-init-) Singletons instanziieren. Finanzierungstätigkeit (Beanfactory);
Protected Void FinishbeanFactoryInitialization (configurablelistableBeanFactory Beanfactory) {// Initialisieren von Conversion -Dienst für diesen Kontext. if (beanfactory.containsbean (Conversion_Service_Bean_Name) && beanfactory.istypematch (Conversion_Service_Bean_Name, ConversionService.class)) {beanfactory.setConversionService (beanfactory.getBean (Conversion). } // Registrieren Sie einen standardmäßigen eingebetteten Wert Resolver, wenn kein Bean Post-Processor // (z. if (! beanfactory.hasembeddedValUeresolver ()) {beanfactory.addembeddedValUeresolver (neuer StringValUeresolver () {@Override Public String resolvestringValue (String Strval) {return getenvironment (). } // Initialisieren Sie loadTimeWeaveraware -Bohnen frühzeitig, um ihre Transformatoren frühzeitig zu registrieren. String [] Weaverawarenames = BeanFactory.getBeannamesForForType (loadTimeWeaveraware.class, false, false); für (String Weaverawarename: Weaverawarenames) {getBean (Weaverawarename); } // Hören Sie auf, den temporären Klassenloader für den Typ -Matching zu verwenden. BeanFactory.settemPClassloader (NULL); // Ermöglichen Sie, dass alle Bean -Definition -Metadaten zwischengespeichert werden, ohne weitere Änderungen zu erwarten. BeanFactory.FreezeConfiguration (); // alle verbleibenden (nicht-lazy-init-) Singletons instanziieren. beanfactory.preistantiatesingletons (); }Schauen Sie sich die Preinstantiatesingletons -Methode an
public void preinstantiatesingletons () löscht Beansexception {if (this.logger.isdebugenabled ()) {this.logger.debug ("prästantiagierende Singletons in" + this); } List <string> beannames = new ArrayList (this.beandefinitionNames); Iterator var2 = Beannames.Iderator (); while (true) {while (true) {String beanname; Rootbeandefinition bd; do {do {do {if (! var2.hasnext ()) {var2 = beannames.iterator (); while (var2.hasnext ()) {beanname = (string) var2.next (); Object SingletoninStance = this.getSingleton (Beanname); if (SingletoninStance -Instanz von SmartInitializingingleton) {Final SmartInitializingSingleton Smartsingleton = (SmartInitializingSingleton) Singletoninstance; if (system.getSecurityManager ()! } else {smartSingleton.Afsingletonsinstantiated (); } } zurückkehren; } beanname = (string) var22.next (); bd = this.getMergedLocalbeanDeFinition (Beanname); } while (bd.isabstract ()); } while (! bd.issingleton ()); } while (bd.islazyinit ()); if (this.iscoTTORTORYBEAN (Beanname)) {Final FactoryBean <?> factory = (factoryBean) this.getBean ("&" + Beanname); boolean iseagerinit; if (system.getSecurityManager ()! this.getAccessControlContext ())). booleanValue (); } else {iseAgerinit = factory Instance von SmartFactoryBean && ((SmartFactoryBean) fabrik) .iseAgerinit (); } if (iseAgerinit) {this.getBean (Beanname); }} else {// Registrieren Sie Bean this.getBean (Beanname); }}}}}}}}}}}Verwenden Sie die GetBean -Methode, um alle ungeschriebenen Instanzen durch Reflexion zu erstellen.
Verwenden von eingebetteten Servletbehältern:
Vorteile: Einfach, tragbar
Nachteile: JSP unterstützt standardmäßig nicht, Optimierung und Anpassung sind komplizierter
Schritte zur Verwendung eines externen Servlet -Containers:
1. Das Kriegsprojekt muss erstellt werden, und die Verzeichnisstruktur des Jianhao -Webprojekts ist erforderlich.
2 Eingebettete Tomcat -Abhängigkeitszielen gibt angegeben
3 Schreiben Sie eine SpringbootServletinitializer -Klasse -Unterklasse und überschreiben Sie die Konfigurationsmethode
public class ServletInitializer erweitert SpringbootServletInitializer {@Override Protected SpringApplicationBuilder configure (SpringApplicationBuilder -Anwendung) {return application.sources (Springboot04WebjspApplication.class); }}4 Starten Sie den Server
Der Unterschied zwischen Start -Jar -Paket und Kriegspaket
JAR -Paket: Führen Sie die Auslaufmethode der Springbootapplication aus, starten Sie den IOC -Container und erstellen Sie dann einen eingebetteten Servlet -Container
Kriegspaket: Starten Sie zunächst den Servlet -Server, der Server startet die Springboot -Anwendung (SpringbootServletinitizer) und dann startet der IOC -Container
Servlet 3.0+ Regeln
1. Serverstart (Webanwendungsstart), die ServletContainerLnitializer -Instanz in allen JAR -Paketen in der aktuellen Webanwendung wird erstellt.
2 Die Implementierung von ServletContainerInitializer wird im Ordner Meta-Inf/Services des JAR-Pakets platziert
3 Sie können auch die @handLestypes -Annotation verwenden, um die angegebene Klasse zu laden, wenn die Anwendung gestartet wird.
Externer Tomcat -Prozess und Prinzipien
① Tomcat starten
② Nach den oben beschriebenen Servlet3.0+ -Regeln finden Sie im Spring -Webmodul eine Datei namens javax.servlet.servletContainerInitializer, und der Inhalt der Datei ist org.springframework.web.springServletContaineritializer -Klasse.
③ Schauen Sie sich die Definition von SpringServletContainerInitializer an
@HandLestypes (WebApplicationInitializer.class) öffentliche Klasse SpringServletContainerInitializer implementiert ServletContainerInitializer { /** * Delegieren Sie die {@Code servletContext} an {@link web ApplicationInitializer} * Implementierungen, die auf dem Anwendungsklassen -Klassenklassen vorhanden sind. * <p> Da diese Klasse@{@code Handadypes (WebApplicationInitializer.Class)} deklariert, scannen die Container von Servlet 3.0+ automatisch den Klassenpfad für Implementierungen * von Spring's {@Code WebApplicationInitializer -Schnittstelle} und bieten den Satz aller Typen. * <p> Wenn nein {@code webapplicationInitializer} Implementierungen auf dem Klassenpfad gefunden werden, * ist diese Methode effektiv ein No-op. Eine Protokollnachricht auf Info-Level wird ausgegeben. * <p> unter der Annahme, dass ein oder mehrere {@Code webapplicationInitializer} festgestellt werden, * sie werden instanziiert (und <em> sortiert </em>, wenn die@{@link * org.springFramework.Core.Annotation.Order @Order} Annotation vorhanden ist. Implementiert. Servlet -API -Komponenten wie Filter. onStartup (set <class <? >> webAppinitializerclasses, ServletContext ServletContext) löst ServletException {list <WebapplicationInitializer> Initializer = new LinkedList <WEBAPLICATIONIONILICIERN> (); defend: Some servlet containers provide us with invalid classes, // no matter what @HandlesTypes says... if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) && WebApplicationInitializer.class.isAssignableFrom(waiClass)) { try { //Create instances for all WebApplicationInitializer types and add to the Collection Initializer.Add ((WebApplicationInitializer) Waclass.Newinstance ()); auf classPath "); return;} ServletContext.log (Initializer.size () +" Spring WebApplicationInitializers auf Klassenpfad "); initializer.onstartup (ServletContext);In dem obigen Kommentar sehen Sie, dass SpringServletContainerInitializer alle Klassen von WebApplicationInitializer -Typen übergibt, die von @handLestypes (WebApplicationInitializer.Class) in den festgelegten Parameter der OnStartup -Methode annotiert sind und Instanzen für diese WebaplicationInitializer -Typen durch Reflexion erstellt.
④ Methode am Ende hat jede WebApplicationInitilizer -Implementierung eine eigene OnStartup -Methode aufgerufen
⑤ WebApplicationInitializer verfügt über eine abstrakte Implementierungsklasse SpringbootServletInitializer (denken Sie daran, wir haben diese abstrakte Klasse geerbt), und die OnStartup -Methode jeder WebApplicationInitializer -Instanz (einschließlich SpringbootServletInitializer) wird bezeichnet:
public abstract Class SpringbootServletInitializer implementiert WebApplicationInitializer {// Andere Code ... @Override public void onStartup (ServletContext ServletContext) servleTexception {// logger -Initialisierung wird in Case a ordned // logServletContextinitializer verwendet. // IOC Container WebApplicationContext RootAppContext = CReaterootApplicationContext (ServletContext); if (rootAppContext! } else {this.logger.debug ("no contextloaderListener registriert," + "creatreoTapplicationContext () nicht" + "einen Anwendungskontext zurückgeben"); }} Protected WebApplicationContext CreaterootApplicationContext (ServletContext ServletContext) {// Erstellen Sie den Spring Application Builder und setzen Sie die relevanten Eigenschaften SpringApplicationBuilder Builder = createSPringApplicationBuilder (); StandardsServLede -Umweltumgebung = neuer StandardsServlede -Umwelt (); Umwelt.initPropertySources (ServletContext, NULL); Builder.Environment (Umwelt); Builder.main (getClass ()); ApplicationContext übergeordnet = getExistingRootWebApplicationContext (ServletContext); if (parent! servletContext.setAttribute (WebApplicationContext.root_Web_Application_Context_attribute, null); Builder.Initializers (New ParentContextApplicationContextInitializer (Parent)); } builder.initializers (neuer servletContextApplicationContextInitializer (ServletContext)); Builder.ContextClass (AnnotationConFigembeddedWebApplicationContext.class); // Nach dem Aufrufen der Konfigurationsmethode und des Erstellens eines Webprojekts zum Kriegstyp, da die Unterklasse von SpringbootServletinitializer die Konfigurationsmethode überschreibt, wird hier die Konfigurationsmethode aufgerufen, die wir definiert haben. Builder = configure (Builder); // Eine Frühlingsanwendung wird über die Builder Spring Application Application = Builder.build () erstellt. if (application.getSources (). isEmpty () && AnnotationUtils .FindAnnotation (getClass (), configuration.class)! = null) {Application.getSources (). add (getClass ()); } Assert.state (! Application.getSources (). IsEmpty (), "wurden keine Springapplication -Quellen definiert. Entweder überschreien Sie die" + "-Methode oder fügen Sie eine @Configuration -Annotation zu"); // Fehlerseiten registriert sind, wenn (this.registererRorPageFilter) {application.getSources (). Add (FehlerpageFilterConfiguration.class); } // Spring Application Return Run (Anwendung) starten; } // Spring Application startet, erstellt und gibt den geschützten IOC -Container -WebApplicationContext Run (SpringApplication Application) {return (WebApplicationContext) application.run (); }}Wenn die SpringbootServletinitializer -Instanz die OnStartUp -Methode ausführt, wird die Run -Methode über die CreaterootApplicationContext -Methode ausgeführt. Der nächste Vorgang entspricht dem Auslaufprozess der Anwendung in Form eines JAR -Pakets. Der IOC -Container wird intern erstellt und zurückgegeben. Die Anwendung in Form eines Kriegspakets erstellt jedoch den Servlet -Container während des Erstellens des IOC -Containers nicht mehr.
Zusammenfassen
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, dass der Inhalt dieses Artikels einen gewissen Referenzwert für das Studium oder die Arbeit eines jeden hat. Wenn Sie Fragen haben, können Sie eine Nachricht zur Kommunikation überlassen. Vielen Dank für Ihre Unterstützung bei Wulin.com.