최근에, 나는 스프링의 소스 코드를 살펴 보았고 갑자기 web.xml 구성없이 스프링이 어떻게 자체적으로 시작되었는지 궁금했습니다. 제한된 능력과 처음으로 소스 코드를 읽고 블로그를 게시했을 때, 무엇을 해야할지 모르겠다면 용서 해주세요 ~
내가 사용하는 IDE는 Intellij Idea이며, MyClipse보다 소스 코드를 읽기 쉽고 검은 색 배경에서 매우 좋아합니다. 그런 다음 프로젝트는 Maven Tomcat7 플러그인에서 실행됩니다. 스프링 버전은 4.3.2. release입니다.
순수한 주석 구성이있는 스프링 웹을 작성한 경우 Bean을로드하기 위해 초기화 클래스를 상속해야한다는 것을 알아야합니다. 그러면 우리의 맞춤형 기능과 Bean 은이 클래스에서로드됩니다. 아래는 내 webinitializers 중 하나입니다
@Order (1) public class webmvcinit는 acpractAntationConfigDispatcherServleTinitializer {protected class <?> [] getRootConfigClasses () {return new Class [] {rootconfig.class, websecurityConfig.class}; } protected class <?> [] getServletConfigClasses () {return new Class [] {webConfig.class}; } protected String [] getServletMappings () {return new String [] { "/"}; } @override Protected Filter [] getServletFilters () {return new Filter [] {New HiddenhttpMethodFilter ()}; }}먼저, AbstractAntationConfigDispatcherservletinitializer 클래스의 구조를보십시오. 이것은 또한 아이디어의 UML 기능입니다. 다이어그램을 마우스 오른쪽 버튼으로 클릭하십시오-> 클래스의 다이어그램 표시.
그런 다음 AbstractAntationConfigDispatcherservletinitializer를 직접 클릭합니다. 이 클래스는 4 가지 방법만으로 매우 간단하다는 것을 알 수 있습니다. 그런 다음 CreaterootApplicationContext ()에주의를 기울입니다.
@override protected webApplicationContext createrOutApplicationContext () {class <?> [] configClasses = getRootConfigClasses (); if (! objectUtils.isempty (configClasses))) {annotationConfigWebApplicationContext rootappContext = new AnnotationConfigWebApplicationContext (); rootappContext.register (configClasses); rootappContext를 반환합니다. } else {return null; }}이 방법은 대략 사용자 (프로그래머)가 보낸 루트 클래스를 얻은 다음 콩을 등록하는 것을 의미합니다. 이것들은 우리가 걱정하는 것이 아니지만,이 방법은 시작 후에 실행되어야 하므로이 방법을 찾을 수 있습니다.
아이디어 아래 Ctrl+G는 호출 할 메소드 또는 클래스를 찾은 다음 검색 범위를 프로젝트 및 라이브러리로 설정할 수 있습니다.
AbstractContextLoaderInitializer에서 registerContextLoaderListener (ServleContext ServletContext) 메소드는 서브 클래스의 CreaterOpplicationContext ()를 호출하여 WebApplicationContext (ServerContextLoaderListener) 방법의 호출자를 찾는다는 것을 발견했습니다. 결과적으로,이 클래스의 Onstartup (ServletContext ServletContext)이라는 것이 밝혀졌습니다. AbstractContextLoaderInitializer 클래스는 아래에 게시됩니다.
공개 초록 클래스 AbstractContextLoaderInitializer는 웹 클래스에 사용할 수있는 WebApplicationInitializer { / ** logger* / 보호 된 최종 logger = logfactory.getLog (getClass ()); @override public void onstartup (servletcontext servletcontext) servletexception {registerContextLoaderListener (servletContext); } /*** 주어진 서블릿 컨텍스트에 대해 {@link contextloaderListener}를 등록하십시오. * {@Code ContextLoaderListener}는 {@Link #CreaterOutApplicationContext ()} 템플릿 메소드에서 응용 프로그램 컨텍스트 *로 초기화됩니다. * @Param ServletContext 청취자를 등록하기위한 서블릿 컨텍스트 */ protected void registerContextLoaderListener (servletContext servletContext) {webApplicationContext rootappContext = createrOutApplicationContext (); if (rootAppContext! = null) {ContextLoaderListener Listener = new ContextLoaderListener (rootAppContext); Listener.setContextInitializers (getRootApplicationContextInitializers ()); servletcontext.addlistener (리스너); } else {logger.debug ( "ContextLoaderListener는" + "CreaterOutApplicationContext ()가 응용 프로그램 컨텍스트를 반환하지 않았기 때문에 등록되지 않음"); }} /** * * {@Code ContextLoaderListener}에 제공 될 "<strong> root < /strong>"응용 프로그램 컨텍스트를 작성합니다. * <p> 반환 된 컨텍스트는 * {@link contextloaderListener#contextLoaderListener (webApplicationContext)}로 위임되며 {@code dispatcherServlet} 응용 프로그램 * 컨텍스트에 대한 상위 컨텍스트로 *가 설정됩니다. 따라서 일반적으로 중간 계층 서비스, 데이터 소스 등을 포함합니다. * @ @return root Application 컨텍스트 또는 {@Code NULL} 루트 컨텍스트가 원하는 * @see org.springframework.web.servlet.support.abstractDispatcherServleTeNitializer */ Propectected webapplicationcontextontextcontextcontextcontextcontextcontextcontextcontextcontextcontext의 Creptercontectontextcont의 Creptercontextcontet는 CreatePollicationcontectontextcontextcont를 텍스트에 포함하지 않습니다. /** * {@Code ContextLoaderListener}가 생성되는 루트 응용 프로그램에 적용 할 애플리케이션 컨텍스트 초기화기를 지정하십시오. * @since 4.2 * @see #createrootApplicationContext () * @see ContextLoaderListener #setContextInitializers */ Protected ApplicationContextInitializer <?> [] getRootApplicationContextInitializers () {return null; }}AbstractDispatcherservletinitializer Abstract 클래스를 건너 뛰었습니다 (UML 다이어그램 참조). 이 클래스는 주로 Spring MVC 및 기타 기능의 구현 인 Dispatcherservlet을 구성합니다.
그렇다면 누가 AbstractContextLoaderInitializer를로드 할 것인가? WebApplicationInitializer는 이미 인터페이스이며 호출 할 초록 클래스는 없습니다. 그래서 WebApplicationInitializer 인터페이스를 검색하려고했습니다. Spring과 같은 대규모 프로젝트는 확실히 인터페이스 지향적이므로 호출은 일반적으로 인터페이스에 기록됩니다. 그런 다음 ServletContainerinitializer 인터페이스를 구현하는 Springservletcontainerinitializer 클래스를 발견했습니다. 이 클래스는 아마도 모든 webapplicationinitializers를 시작하는 것을 의미합니다. 이 수업은 우리의 목표에 매우 가깝다고 말할 수 있습니다. 아래는 Springservletcontainerinitializer입니다
@handlestypes (webApplicationInitializer.class) public class springservletContainerInitializer 구현 servletContainerInitializer {@override public void onstartup (set <class <?>> webAppinitializerclasses, servletContextContext) servletexception {webapplicationInitializer = new wearlizeNitiOlizer = servletContextContext). LinkedList <WebApplicationInitializer> (); if (webAppinitializerClasses! = null) {for (class <?> waiclass : webAppinitializerclasses) {// 일부 서플릿 컨테이너는 @handlestypes가 말하는 내용에 상관없이 잘못된 클래스를 제공합니다 ... if (! waiclass.isinterface (! modifier.isabstract)) webApplicationInitializer.class.isAssignableFrom (waiclass)) {try {initializers.add ((webApplicationInitializer) waiclass.newinstance ()); } catch (Throwable ex) {Throw New ServleTeXception ( "WebApplicationInitializer 클래스를 인스턴스화하지 못했습니다", Ex); }}}}} if (initializers.isempty ()) {servletcontext.log ( "classPath에서 감지 된 스프링 웹 abapplicationInitializer 유형 없음"); 반품; } servletcontext.log (이니셜 라이저. AnnotationAwareOrdercomparator.sort (이니셜 라이저); for (webApplicationInitializer Initializer : Initializers) {initializer.onstartup (servletcontext); }}}마지막 Foreach에서 모든 WebApplicationInitializers를 시작하십시오. 그렇다면 누가 springservletcontainerinitializer를 시작할 것인가? 봄은 분명히 그 자체로 시작할 수 없습니다.
웹 환경에는 웹 컨테이너 만 있습니다. 우리는 위의 장소 중 하나에서 중단 점을 만들고 디버깅 할 수 있습니다 (사실, 정확하고 빠른 프로세스 전반에 걸쳐 완전히 디버그 할 수 있지만 검색의 의미가 부족하고 도로를 따르는 풍경은 상당히 좋습니다).
package org.apache.catalina.core에서 StandardContext 클래스의 시작 방법을 볼 수 있습니다. 이것은 이미 Tomcat의 범위에 있으므로 우리의 목표가 달성되었습니다. ServletContainerinitializer 인터페이스는 스프링 패키지 아래에 있지 않지만 javax.servlet입니다.
Tomcat은 Javax.servlet의 ServletContainerinitializer 인터페이스를 사용하여 컨테이너 에서이 인터페이스를 구현하는 클래스를 찾은 다음 OnStartup을 호출 한 다음 Spring의 SpringservletContainerinitializer는 우리 직접 작성한 webinitializer를 포함하는 모든 WebApplicationInitializers를 시작할 수 있다고 생각합니다. 또한 Spring Security는 웹 applicationInitializer를 구현하기 위해 주석으로 구성되므로 Spring은 매우 확장 가능합니다. Tomcat 메커니즘을 이해하기 위해 다음 며칠 안에 Tomcat 소스 코드를 살펴 보겠습니다.
위는이 기사의 모든 내용입니다. 모든 사람의 학습에 도움이되기를 바랍니다. 모든 사람이 wulin.com을 더 지원하기를 바랍니다.