머리말
이 기사는 주로 Servlet Startup 프로세스 및 Spring Boot의 원칙에 대한 관련 컨텐츠를 소개합니다. 아래에서 많이 말하지 않겠습니다. 자세한 소개를 함께 살펴 보겠습니다.
시작 프로세스 및 원칙 :
1 스프링 부팅 애플리케이션 시작 실행 방법
STOPWATCH STOPWATCH = New StopWatch (); stopwatch.start (); configurableApplicationContext context = null; FailureAnalyzers Analyzers = null; configureHeadsHeadsProperty (); SpringApplicationRunListeners 리스너 = getRunListEners (Args); 청취자.starting (); {ApplicationArguments ApplicationArguments = new DefaultApplicationArguments (Args); 구성 가능한 환경 환경 = 준비 환경 (청취자, 응용 프로그램); 배너 printedbanner = printbanner (환경); // ApplicationContext 컨테이너 context를 만듭니다 = createApplicationContext (); 분석기 = 새로운 failureAnalyzers (컨텍스트); PrepareContext (컨텍스트, 환경, 청취자, 응용 프로그램, Printedbanner); // 새로 고침 IOC 컨테이너 CORTHERCONTEXT (Context); AfterRefresh (컨텍스트, 응용 프로그램); 청취자. 피니쉬 (컨텍스트, NULL); stopwatch.stop (); if (this.logstartupinfo) {new startUpInfologger (this.MainApplicationClass) .LogStarted (getApplicationLog (), stopWatch); } 반환 컨텍스트; } catch (Throwable ex) {handlerunfailure (컨텍스트, 청취자, 분석기, 예); 새로운 불법 상태를 던지십시오 (예); }2 CreateApplicationContext () : IOC 컨테이너를 만듭니다. 웹 애플리케이션 인 경우 AnnotationConfigemeddedWebApplication의 IOC 컨테이너를 작성하십시오. 그렇지 않은 경우, 주석을 세우는 IOC 컨테이너를 만듭니다.
공개 정적 최종 문자열 default_context_class = "org.springframework.context." + "Annotation.annotationConfigApplicationContext"; /** * 웹 * 환경에 기본적으로 사용될 응용 프로그램 컨텍스트의 클래스 이름. */ public static final String default_web_context_class = "org.springframework." + "boot.context.embedded.annotationConfigemedDedDedWebApplicationContext"; 보호 된 configurableApplicationContext createEapplicationContext () {class <?> contextClass = this.ApplicationContextClass; if (contextclass == null) {try {// 응용 프로그램 환경에 따라 다른 IOC 컨테이너를 만듭니다. contextclass = class.forname (this.webenvironment? default_web_context_class : default_context_class); } catch (classNotFoundException ex) {Throw New New ElegalStateException ( "불가능한 기본 ApplicationContext를 만들 수 없습니다." + "ApplicationContextClass를 지정하십시오", ex); }} return (configurableApplicationContext) beanutils.instantiate (contextClass); }3 CROTMEYTCONTEXT (CONTEXT) SPRING BOOT IOC 컨테이너를 새로 고칩니다 (컨테이너 개체 생성, 컨테이너 초기화 및 컨테이너의 각 구성 요소 생성)
private void refreshContext (configurableApplicationContext context) {새로 고침 (컨텍스트); if (this.registershutdownhook) {try {context.registershutdownHook (); } catch (AccessControleXception EX) {// 일부 환경에서는 허용되지 않습니다. }}}}4 새로 고침 (컨텍스트); 방금 만든 IOC 컨테이너를 새로 고치십시오
보호 된 void refresh (ApplicationContext ApplicationContext) {assert.isinstanceof (AbstractApplicationContext.class, ApplicationContext); (((AbstractApplicationContext) ApplicationContext) .refresh (); }5. Parent Class Comph 다음 () 메소드를 호출하십시오
public void refresh ()는 beansexception, delegalstateException {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 초록 부모 클래스의 서브 클래스 임베디드 WebApplicationContext의 onrefresh 메소드 추상 AbstracticationContext
@override protected void onrefresh () {super.onrefresh (); {createembeddedservletcontainer (); } catch (Throwable ex) {Throw New ApplicationContexTexception ( "임베디드 컨테이너를 시작할 수 없음", ex); }}7 CreateEmbeddedServletContainer에서 내장 된 서블릿 컨테이너 공장이 얻어지고 서블릿은 컨테이너 공장에서 생성됩니다.
개인 void createEmbeddedServletContainer () {embeddedServletContainer localContainer = this.EmbeddedServletContainer; ServletContext localserVletContext = getServletContext (); if (localContainer == null && localservletcontext == null) {// 내장 된 서블릿 컨테이너 공장 내장 내장 내장 ContainerFactory ancorfactory = getembeddedServletContainerActory (); // 컨테이너 공장을 기반으로 해당 내장 된 서블릿 컨테이너를 가져옵니다. } else if (localServletContext! = null) {try {getSelfinItializer (). onstartup (localserVletContext); } catch (servletexception ex) {새로운 ApplicationContexTexception 던지기 ( "Servlet Context를 초기화 할 수 없음", Ex); }} initPropertySources (); }8 IOC 컨테이너에서 서블릿 컨테이너 공장을 받으십시오
// embeddedWebApplicationContext#getEmbedDedServletContainerFactory Protectored EmbedDedServletContainerFactory getEmbeddedServletContainerFactory () {// Bean 이름을 사용하여 Hierarchy String을 고려하지 않도록 [] BeanNames = GetBeannamesType (embedservervletConeRCOLTORC.CONTACTORTORY.CLACTORY.CORCOLTORTOY); if (beannames.length == 0) {Throw New ApplicationContexTexception ( "" " +"embeddedServletContainerFactory Bean "으로 인해 내장 된 WebApplicationContext를 시작할 수 없습니다."); } if (beannames.length> 1) {throw new applicationcontextexception ( "여러" + "embeddedservletcontainerfactory beans로 인해 내장 된 WebApplicationContext를 시작할 수 없습니다 :" + stringUtils.ArrayTocomMadElimitedString (beannames)); } let }9 서블릿 컨테이너 공장을 사용하여 내장 된 서블릿 컨테이너를 얻으십시오. 사용해야 할 컨테이너 공장은 구성 환경 종속성에 따라 다릅니다.
this.embeddedservletcontainer = containerFactory .getEmbeddedServletContainer (getSelfinitializer ());
10 위의 생성 프로세스는 먼저 IOC 컨테이너를 시작한 다음 내장 된 서블릿 컨테이너를 시작한 다음 직접 만든 컨트롤러와 같이 IOC 컨테이너에서 만들지 않은 나머지 객체를 검색합니다.
// 남은 모든 (비 게으른 이니트) 싱글 톤을 인스턴스화합니다. 마감 처리 (beanfactory);
보호 된 void finishedbeanfactoryInitialization (configurableBeListableBeanFactory beanfactory) {//이 컨텍스트에 대한 변환 서비스 초기화. if (beanfactory.containsbean (converion_service_bean_name) && beanfactory.istypematch (converion_service_bean_name, converionservice.class)) {beanfactory.setconversionservice (beanfactory.getbean (conversion_service_bean_name, conversionservice.crassservice.class)); } // Bean Post-Processor // (PropertyPlaceHolderConfigurer Bean 등)가없는 경우 기본 임베디드 값 리졸버를 등록하십시오. if (! beanfactory.hasembeddedValueresolver ()) {beanfactory.addemeddedValueresolver (new StringValueresolver () {@override public string resolvestringvalue (String Strval) {return getEnvironment (). resolveplaceanders (strval); } // 트랜스포머를 일찍 등록 할 수 있도록 LoadtimeWeaveraware Bean을 일찍 초기화합니다. 문자열 [] weaverawarenames = beanfactory.getBeannamesfortype (loadTimeWeaVeraWare.class, false, false); for (String weaverawarename : weaverawarenames) {getbean (weaverawarename); } // 유형 일치에 임시 클래스 로더 사용을 중지합니다. beanfactory.settempclassloader (null); // 추가 변경을 기대하지 않고 모든 Bean 정의 메타 데이터를 캐싱 할 수 있습니다. beanfactory.freezeconfiguration (); // 남은 모든 (비 게으른 이니트) 싱글 톤을 인스턴스화합니다. beanfactory.preinstantiatesingletons (); }사전 입장선 방법을 확인하십시오
공개 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; RootBeendefinition BD; do {do {do {if (! var2.hasnext ()) {var2 = beannames.iterator (); while (var2.hasnext ()) {beanname = (string) var2.next (); Object SingletonInstance = this.getSingleton (Beanname); if (smartinitializingsingleton의 SingletonInstance 인스턴스) {최종 SmartInitializingsingingleton smartsingleton = (SmartInitializingsingingleton) Singletoninstance; if (system.getSecurityManager ()! = null) {accessController.doprivileged (new PrivilegedAction <botal> () {public Object Run () {SmartSingleton.AftersingEnstantiated (); return null;}}, this.getAccessControlContext (); } else {smartsingleton.aftersingletonSinstantiated (); } } 반품; } 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); 부울 iseagegerinit; if (system.getSecurityManager ()! = null && smartFactoryBean의 팩토리 인스턴스) {isegerinit = ((boolean)) accesscontroller.doprivileged (새로운 권한 <boolean> () {public boolean run () {return ((smartCactoryBean) factory);}}, this.getAccessControlContext ())). booleanValue (); } else {iseageRinit = SmartFactoryBean의 공장 인스턴스 && ((SmartFactoryBean) Factory) .iseageRinit (); } if (iseageRinit) {this.getBean (beanname); }} else {// bean this.getBean (beanname); }}}}}}}}}}}getbean 방법을 사용하여 반사를 통해 창조되지 않은 모든 인스턴스를 만듭니다.
임베디드 서블릿 컨테이너 사용 :
장점 : 간단하고 휴대용
단점 : JSP는 기본적으로 지원하지 않으며 최적화 및 사용자 정의가 더 복잡합니다.
외부 서블릿 컨테이너 사용 단계 :
1. 전쟁 프로젝트를 만들어야하고 Jianhao 웹 프로젝트의 디렉토리 구조가 필요합니다.
2 내장 Tomcat 종속성 범위가 제공된 것을 지정합니다
3 SpringBootservleTinitializer 클래스 서브 클래스를 작성하고 구성 메소드를 재정의합니다.
공개 클래스 Servletinitializer 확장 SpringBootservletinitializer {@override Protected SpringApplicationBuilder Configure (SpringApplicationBuilder Application) {return Application.Sources (SpringBoot04webjSpapplication.class); }}4 서버를 시작하십시오
시작 JAR 패키지와 전쟁 패키지의 차이점
JAR 패키지 : SpringBootApplication의 실행 방법을 실행하고 IOC 컨테이너를 시작한 다음 내장 된 서블릿 컨테이너를 만듭니다.
전쟁 패키지 : 먼저 서틀 서버를 시작하고 서버는 SpringBoot 응용 프로그램 (SpringBootservleTinitizer)을 시작한 다음 IOC 컨테이너를 시작합니다.
서블릿 3.0+ 규칙
1. 서버 시작 (웹 응용 프로그램 시작), 현재 웹 응용 프로그램의 모든 JAR 패키지의 ServletContainerLnitializer 인스턴스가 생성됩니다.
2 ServletContainerinitializer의 구현은 JAR 패키지의 Meta-Inf/Services 폴더에 배치됩니다.
3 @handlestypes 주석을 사용하여 응용 프로그램이 시작될 때 지정된 클래스를로드 할 수 있습니다.
외부 Tomcat 프로세스 및 원칙
tomcat을 시작하십시오
위에서 설명한 Servlet3.0+ 규칙에 따르면, Spring Web Module에서 javax.servlet.servletcontainerinitializer라는 파일을 찾을 수 있으며 파일의 내용은 springservletcontainitializer classer를로드하는 데 사용되는 org.springframework.web.springservletcontainerinitializer입니다.
springservletcontainerinitializer의 정의를 살펴보십시오
@handlestypes (webApplicationInitializer.class) public class springservletcontainerinitializer는 servletcontainerinitializer { /** * {@code servletcontext}를 {@link ebapplicationInitializer} * 구현을 응용 프로그램 클래스 경로에 표시합니다. * <p>이 클래스는@{@code handlestypes (webApplicationInitializer.class)}를 선언하기 때문에 * Servlet 3.0+ 컨테이너는 Spring의 {@code webApplicationInitializer} 인터페이스의 구현 *을 자동으로 스캔하고 {@code webAppinitializer}이 모든 유형의 세트를 {@code webAppinitializer}를 제공합니다. * <p> NO {@Code WebApplicationInitializer} 구현이 ClassPath에서 찾을 수있는 경우 *이 메소드는 사실상 NO-OP입니다. {@code servletcontainerinitializer}가 실제로 호출되었지만 * 아니요 {@code webApplicationInitializer} 구현이 발견되었다는 사용자에게 알림 *에 인포 레벨 로그 메시지가 발행됩니다. * <p> 하나 이상의 {@code webApplicationInitializer} 유형이 감지되었다고 가정하면, * {@link * org.spramework.core.annotation. @order} 주석이 존재하거나 * {@link org. @link webApplicationInitializer#onstartup (servletContext)} * 메소드가 각 인스턴스에서 {@code servletcontext}를 위임하면 각 인스턴스가 스프링 * {@code dispatcherervlet}, 스프링 {@code conte ' 필터와 같은 API 구성 요소. onstartup (set <class <? >> webappinitializerclasses, servletcontext servletcontext) servletexception {list <webApplicationInitializer> new linkedList <webApplicationInitializer> (webAppinitializerclasses! = null); 방어 : 일부 서블릿 컨테이너는 @handlestypes가 말하는 내용에 상관없이 잘못된 클래스를 제공합니다 ... if (! waiclass.isinterface () &&! modifier.isabstract (waiclass.getModifiers ()) && webApplicationInitializer.class.isAssignableFrom (waiclass)) {// webapplascationin and all webapplationin and all webapplationiniater and webapplicationication {// Collection Initializers.add ((WebApplicationInitializer) waiclass.newinstance ()} catch (wash new servletexception) { "WebApplicationInitializer 클래스를 인스턴스화하지 못한다",}} if (string webapty ()). ClassPath "); return;} servletcontext.log (initializers.size () +"classPath에서 감지 된 스프링 웹 애플리케이션 인디 니너즈 "; AnnotationAwareArderComparator.sort (Initializers); // 각 웹 applicationInitializer (webapplicationInitializer)를 호출합니다. 이니셜 라이저.위의 긴 주석에서 Springservletcontainerinitializer는 @handlestypes (webApplicationInitializer.class)에 의해 주석이 붙은 모든 웹 클래스의 웹 클래스를 OnStartup 메소드의 세트 매개 변수로 전달하고 반사에 의해 이러한 웹 applicationInitializer 유형에 대한 인스턴스를 생성한다는 것을 알 수 있습니다.
④ 끝에있는 메소드, 각 webApplicationInitilizer 구현은 자체 OnStartup 메소드를 호출합니다.
WebApplicationInitializer는 추상 구현 클래스 SpringBootServleTinitializer (이 추상 클래스를 상속 받았음을 기억하십시오)를 가지고 있으며, 각 webApplicationInitializer 인스턴스 (SpringBootservleTinitializer 포함)의 onstartup 메소드는 다음을 호출합니다.
공개 초록 클래스 SpringBootservletinitializer는 웹 applicationInitializer {// 다른 코드 ... @override public void onstartup (servletContext servletcontext)을 servletexception {// logger 초기화는 // logservletcontextinitializer가 사용되는 경우를 대비하여 지연됩니다. // IOC 컨테이너 만들기 웹 컨테이너 webApplicationContext rootappContext = CreaterOutApplicationContext (ServletContext); if (rootappContext! = null) {servletContext.addListener (new ContextLoaderListener (rootappContext) {@Override public void contextInitialized (servletContexTevent event) {// 응용 프로그램 컨텍스트가 이미 초기화 되었기 때문에 no-op); } else {this.logger.debug ( "ContextLoaderListener는" + "CreaterootApplicationContext ()가" + "응용 프로그램 컨텍스트를 반환하지 않았다"); }} 보호 된 webApplicationContext CreaterOutApplicationContext (ServletContext ServletContext) {// 스프링 애플리케이션 빌더를 생성하고 관련 속성을 설정하고 springApplicationBuilder builder = createSpringApplicationBuilder (); StandardservleTenvironment Environment = New StandardservleTenvironment (); Environment.initPropertySources (ServletContext, NULL); Builder.environment (환경); builder.main (getClass ()); ApplicationContext parent = getExistingRootWebApplicationContext (ServletContext); if (parent! = null) {this.logger.info ( "루트 컨텍스트가 이미 생성 (부모로 사용)); servletcontext.setattribute (webApplicationContext.root_web_Application_context_attribute, null); builder.initializers (new ParentContextApplicationContexInitializer (parent)); } builder.initializers (new servletcontextApplicationContInitializer (servletContext)); builder.contextClass (AnnotationConfigemedDedWebApplicationContext.class); // 구성 메소드를 호출하고 전쟁 유형 웹 프로젝트를 작성한 후 SpringBootservleTinitializer의 서브 클래스가 구성 메소드를 무시하기 때문에 여기에서 정의한 서브 클래스로 재정의 된 구성 메소드가 여기에서 호출됩니다. Builder = 구성 (Builder); // 스프링 애플리케이션은 빌더를 통해 구축됩니다. SpringApplication Application = Builder.build (); if (application.getSources (). isempty () && annotationUtils .findAntation (getClass (), configuration.class)! = null) {application.getSources (). add (getClass ()); } assert.state (! application.getSources (). isempty (), "SpringApplication 소스가 정의되지 않았습니다." + "구성 메소드를 재정의하거나 @Configuration 주석을 추가하십시오"); // 오류 페이지가 등록되어 있는지 확인하십시오. } // 시작 스프링 애플리케이션 return run (응용 프로그램); } // 스프링 애플리케이션이 시작, 생성 및 반환 및 반환 및 반환됩니다. 보호 된 webApplicationContext run (SpringApplication Application) {return (webApplicationContext) application.run (); }}SpringBootservleTinitializer 인스턴스가 OnStartup 메소드를 실행하면 CreaterootApplicationContext 메소드를 통해 실행 메소드가 실행됩니다. 다음 프로세스는 항아리 패키지 형태로 시작된 응용 프로그램의 실행 프로세스와 동일합니다. IOC 컨테이너는 내부적으로 생성되어 반환됩니다. 그러나 전쟁 패키지 형태의 응용 프로그램은 IOC 컨테이너를 생성하는 과정에서 더 이상 서블릿 컨테이너를 생성하지 않습니다.
요약
위는이 기사의 전체 내용입니다. 이 기사의 내용에 모든 사람의 연구 나 작업에 대한 특정 참조 가치가 있기를 바랍니다. 궁금한 점이 있으면 의사 소통을 위해 메시지를 남길 수 있습니다. Wulin.com을 지원 해주셔서 감사합니다.