1. 배경
최근에 프로젝트 패키지 스캔 문제로 인해 문제를 해결하는 과정에서 Spring과 SpringMVC가 부모-자식 컨테이너 관계를 가지고 있음을 발견했으며, 이로 인해 패키지 스캔 문제가 종종 발생합니다. 여기서 우리는 Spring과 SpringMVC의 부모-자식 컨테이너 관계를 분석하고 이해하고 Spring 및 SpringMVC 구성 파일에서 공식 권장 패키지 스캔 방법을 제공합니다.
2. 개념 이해와 지식은 기초를 마련합니다
Spring의 전반적인 프레임 워크의 핵심 개념에서 컨테이너는 핵심 아이디어이며,이 아이디어는 Bean의 전체 수명주기를 관리하는 데 사용됩니다. 프로젝트에는 반드시 단 하나의 컨테이너 만있는 것은 아닙니다. 스프링에는 여러 컨테이너가 포함될 수 있으며 컨테이너는 상단 및 하부 레벨을 갖습니다. 현재 가장 일반적인 시나리오는 프로젝트에 Spring과 SpringMVC의 두 프레임 워크를 소개하는 것입니다. 그런 다음 실제로는 두 개의 컨테이너입니다. Spring은 부모 용기이며 SpringMVC는 자식 컨테이너입니다. Spring Parent Container에 등록 된 Bean은 SpringMVC 컨테이너에 보이는 반면 SpringMVC 컨테이너에 등록 된 Bean은 Spring Parent Container에 보이지 않습니다.
XML을 사용하여 각 Bean을 별도로 구성하지 않고 BATCH 등록을 위해 Unified Annotation 구성을 다음과 같이 사용할 수 있습니다.
<context : component-scan base-package = "com.hafiz.www" />
Spring이 제공 한 참조 설명서 에서이 구성의 기능은 @Component 주석을 사용하는 구성된 기본 패키지 패키지에서 모든 클래스를 스캔하고 컨테이너에 자동으로 등록하는 것입니다. 동시에 @Controller, @Service 및 @Respository의 세 가지 주석이 @Component에서 상속되어 있기 때문에 스캔합니다.
이 프로젝트에서 우리는 종종 다음 구성을 볼 수 있습니다. 실제로 위의 구성을 사용하면 위의 구성이 기본적으로 다음 구성을 켜기 때문에 생략 할 수 있습니다. 다음 구성은 @required, @autowired, @postconstruct, @persistenceContext, @resource, @predestroy 등과 같은 주석을 기본적으로 선언합니다.
<컨텍스트 : 주석 -Config/>
또한 SpringMVC와 관련된 다른 구성이 있습니다. 확인 후 @RequestMapping, @RequestBody, @ResponseBody 등을 선언하기 때문에 SpringMVC에 대해 구성해야합니다. 또한이 구성은 기본적으로 JSON Conversion Parser와 같은 많은 매개 변수 바인딩 방법을로드합니다.
<MVC : 주석 구동 />
스프링 3.1 이전의 위의 문장 구성 버전은 다음 구성 방법과 같습니다.
<!-주석 컨트롤러를 구성합니다. SpringMVC에서 요청 요청 URL을 특정 컨트롤러에 매핑하는 데 사용됩니다-> <bean/> <!-주석 컨트롤러 맵퍼 구성 SpringMVC에서 특정 요청을 특정 메소드에 매핑하는 데 사용됩니다 .-> <bean/>.
Spring3.1 이후의 버전은 다음 구성 방법과 같습니다.
<!-주석 컨트롤러를 구성합니다. SpringMVC에서 요청 요청 URL을 특정 컨트롤러에 매핑하는 데 사용됩니다-> <bean/> <!-주석 컨트롤러 맵퍼 구성 SpringMVC에서 특정 요청을 특정 메소드에 매핑하는 데 사용됩니다 .-> <bean/>.
3. 특정 시나리오 분석
스프링과 스프링 MVC 사이의 컨테이너 충돌의 원인을 자세히 살펴 보겠습니다.
Spring과 SpringMVC라는 두 개의 컨테이너가 있으며 구성 파일은 각각 ApplicationContext.xml 및 ApplicationContext-MVC.xml입니다.
1. <context : component-scan base-package = "com.hafiz.www" />는 ApplicationContext.xml에서 등록 해야하는 모든 Bean을 스캔하고 등록 할 책임이 있습니다.
2. SpringMVC 관련 주석의 사용을 담당하려면 ApplicationContext-MVC.XML에서 <MVC : Annotation-Driven /> 구성을 구성하십시오.
3. 프로젝트를 시작할 때 SpringMVC가 점프 할 수 없다는 것을 알았습니다. 로그의 로그 인쇄 레벨을 디버깅을 위해 디버그로 설정했습니다. SpringMVC 컨테이너의 요청이 특정 컨트롤러에 매핑되지 않는 것으로 나타났습니다.
4. ApplicationContext-mvc.xml에서 <context : component-scan base-package = "com.hafiz.www" /> 구성. 다시 시작한 후 확인이 성공하고 SpringMVC 점프가 유효합니다.
구체적인 이유를 확인하고 소스 코드를보고 SpringMVC의 Dispatcherservlet에서 시작하여 검색하겠습니다. SpringMVC가 초기화되면 @Controller 주석을 사용하여 핸들러인지 확인하는 SpringMVC 컨테이너의 모든 콩을 찾을 것임을 발견했습니다. 1과 2의 2 단계 구성은 현재 SpringMVC 컨테이너가 @controller 주석으로 Bean을 등록하지 않지만 @Controller 주석이있는 모든 Bean은 스프링의 모 컨테이너에 등록되므로 SpringMVC는 프로세서를 찾을 수 없으며 점프 할 수 없습니다. 핵심 소스 코드는 다음과 같습니다.
보호 된 void inithandlermethods () {if (logger.isdebugenabled ()) {logger.debug ( "애플리케이션 컨텍스트에서 요청 매핑을 찾고 있습니다 :" + getApplicationContext ()); } string [] beannames = (this.detecthAndLermeDsinanCestorContexts? beanfactoryUtils.beannamesypeinCludeDancestors (getApplicationContext (), object.class) : getApplicationContext (). getBeannamesype (Object.Class)); for (string beanname : beannames) {if (iShandler (getApplicationContext (). getType (beanname))) {detecthAndLerMethods (beanname); }} Handlermethodsinitialized (gethandlermethods ());}Method Ishandler에서, 우리는 현재 Bean의 주석이 컨트롤러인지 여부를 결정합니다. 소스 코드는 다음과 같습니다.
Protected Boolean ishandler (class <?> beantype) {return AnnotationUtils.findAntation (beantype, controller.class)! = null;}4 단계 구성에서 @Controller 주석이있는 모든 Bean도 SpringMVC 컨테이너에 등록되므로 SpringMVC는 처리를위한 프로세서를 찾을 수 있으므로 정상적으로 점프합니다.
우리는 그것이 올바르게 점프 할 수없는 이유를 발견했습니다. 그래서 해결책은 무엇입니까?
우리는 inithandlermethods () 메소드에서 detecthandlermethodsinancestorcontexts 스위치에서 주로 컨테이너의 어떤 콩이 얻어지고, 모 컨테이너가 포함되어 있는지를 제어합니다. 기본적으로 포함되지 않습니다. 따라서 솔루션은 SpringMVC 구성 파일에서 True에 대한 핸드 링크의 detecthandlermethodsinancestorcontexts 속성을 구성하는 것입니다 (여기서는 특정 프로젝트에 따라 어떤 유형의 핸드 랩핑이 사용되는지 확인해야 함), 부모 용기의 Bean을 감지 할 수 있습니다. 다음과 같이 :
<ean> <property name = "detecthandLermeDsinanCestorContexts"> <alue> true </value> </property> </bean>
그러나 실제 프로젝트에는 많은 구성이있을 것입니다. 우리는 다른 비즈니스 모듈에 따라 공식 권장 사항에 따라 다른 컨테이너로 다른 유형의 콩을 분할합니다. 스프링 부모 컨테이너는 @controller가 주석을 달 수없는 다른 모든 콩의 등록을 담당하는 반면, SpringMVC는 @controller가 주석을 달린 Bean의 등록에 대해서만 책임을지고 경계를 정류합니다. 구성 방법은 다음과 같습니다
1. ApplicationContext.xml의 Configure :
<!-@controller에 의해 주석이없는 스프링 컨테이너에 콩을 등록하십시오-> <context : component-scan base-package = "com.hafiz.www"> <context : excludefilter type = "annotation"expression = "org.springframework.steretype.controller"/>
2. ApplicationContext-mvc.xml의 구성
<!-@Controller 주석이있는 Bean 만 SpringMVC 컨테이너에 등록되어 있습니다-> <context : component-scan base-package = "com.hafiz.www"use-default-filters = "false"> <context : filter type = "annotation"org.springframework.steretype.controtty.
3. 요약
이러한 방식으로, 공식 제안에 따르면 스프링과 스프링 MVC의 부모-자식 컨테이너 관계와 스캔 및 등록 원리를 이해 한 후에는 관리를 위해 다른 유형의 콩을 다른 컨테이너에 할당 할 수 있습니다. Bean과 같은 문제가있는 경우 SpringMVC를 리디렉션 할 수 없으며 트랜잭션 구성이 실패하면 문제를 신속하게 찾아서 해결할 수 있습니다. 매우 행복합니다
위는이 기사의 모든 내용입니다. 모든 사람의 학습에 도움이되기를 바랍니다. 모든 사람이 wulin.com을 더 지원하기를 바랍니다.