Spring 과 SpringMVC 의 용기 관계 분석

Spring 과 SpringMVC 는 Bean 관리 용기 와 MVC 층 의 기본 프레임 워 크 로 서 이미 많은 WEB 에서 사용 되 었 으 며, 실제 사용 할 때 강력 한 주해 기능 이 있 기 때문에 XML 기반 설정 방식 이 많이 대체 되 었 으 나, 실제 프로젝트 에서 Spring 과 SpringMVC 를 동시에 설정 할 때 이상 한 이상 이 발생 할 수 있 습 니 다. 예 를 들 어 Bean 이 여러 번 로드 되 고 여러 번 예화 되 었 습 니 다.혹은 주입 에 의존 할 때, 빈 은 자동 으로 주입 되 지 않 지만, 분명히 당신 은 이미 이 빈 을 등록 하 였 습 니 다.원인 을 찾 는 것 은 문제 의 근원 을 봐 야 한다. 우 리 는 용기 부터 말 하 자.
Spring 전체 프레임 워 크 의 핵심 개념 에서 용 기 는 핵심 사상 으로 Bean 의 전체 생명 주 기 를 관리 하 는 것 이다. 한 프로젝트 에서 용 기 는 반드시 하나 가 아니 라 Spring 에 여러 개의 용 기 를 포함 할 수 있 고 용 기 는 상하 층 관 계 를 가진다. 현재 가장 흔히 볼 수 있 는 장면 은 한 프로젝트 에서 Spring 과 SpringMVC 라 는 두 개의 프레임 워 크 를 도입 하 는 것 이다.사실은 2 개의 용기, Spring 은 뿌리 용기, SpringMVC 는 그 하위 용기 이 며, Spring 뿌리 용기 에 서 는 SpringMVC 용기 에 있 는 Bean 을 볼 수 없 으 며, SpringMVC 용기 에 서 는 Spring 뿌리 용기 에 있 는 Bean 을 볼 수 있다. 즉, 하위 용기 에 서 는 부모 용기 에 등 록 된 Bean 을 볼 수 있 고, 그렇지 않 으 면 안 된다.이 점 을 이해 하 는 것 은 매우 중요 하 다. 이것 은 규칙 이기 때문에 Spring 이 스스로 설정 한 것 이다. 그러나 아래 를 보면 우 리 는 이 규칙 을 묵인 하지 않 는 곳 이 있다 는 것 을 알 게 될 것 이다.
우리 가 주 해 를 사용 할 때 Bean 등록 기능 의 실현 은 모든 Bean 에 XML 을 설정 할 필요 가 없습니다. 통 일 된 다음 설정 만 사용 하면 됩 니 다.
<context:component-scan base-package=“com.test" />

Spring 이 제공 하 는 참고 매 뉴 얼 에 따 르 면 이 설정 의 기능 은 기본 가방 에 있 는 모든 @ Component 주 해 를 스 캔 하고 용기 에 자동 으로 등록 하 는 동시에 @ Controller, @ Service, @ Respository 라 는 세 개의 주 해 를 스 캔 하 는 것 입 니 다. 그들 은 @ Component 를 계승 합 니 다.
위 에서 사용 한 스 캔 설정 을 제외 하고 프로젝트 에서 자주 볼 수 있 는 것 은 < context: annotation - config / > 입 니 다. 사실은 위 와 같은 설정 이 있 습 니 다. 이것 은 생략 할 수 있 습 니 다.
또 하나의 SpringMVC 와 관련 된 것 은 < mvc: annotation - driven > 입 니 다. />설정, 검증 을 통 해 이것 은 반드시 설정 해 야 합 니 다. @ RequestMapping 과 결합 하여 사용 되 기 때문에 SpringMVC 프레임 워 크 와 관련 된 지식 을 보충 합 니 다.
Handler Mapping 은 SpringMVC 에서 Request 요청 URL 을 구체 적 인 Controller 로 처리 하 는 데 사용 되 며 그 자체 도 여러 종류 로 나 뉜 다.HandlerAdapter 는 SpringMVC 에서 구체 적 인 요 구 를 처리 하여 구체 적 인 방법 에 투사 하 는 것 으로 그 자체 도 여러 종류 로 나 뉜 다.
@ RequestMapping 이라는 주해 의 주요 목적 은 요청 한 맵 을 처리 하기 위해 구체 적 인 Controller 와 방법 을 등록 하 는 것 입 니 다.하지만 @ RequestMapping 은 < mvc: annotation - driven />사용 해야만 효력 이 발생 한다.
자, 이상 의 기초 지식 이 깔 려 있 습 니 다. 지금 과 같은 사용 장면 에서 Spring 과 SpringMVC 의 용기 가 충돌 하 는 원인 은 어디 에 있 습 니까?
Spring 프로필 applicationContext. xml, SpringMVC 프로필 applicationContext - MVC. xml, 이 항목 에는 2 개의 용기 가 있 습 니 다. 설정 방식 A 는 다음 과 같 습 니 다.
applicationContext. xml 에 < context: component - can 이 설정 되 어 있 습 니 다. base - package = "com. test" / >, 등록 해 야 할 Bean 의 모든 스 캔 작업 을 담당 합 니 다. applicationContext - MVC. xml 에 < mvc: annotation - driven 설정 />,springMVC 관련 주해 의 사용 을 담당 합 니 다. 시작 항목 에서 springMVC 가 효력 을 잃 고 점프 를 할 수 없습니다. log 의 DEBUG 단 계 를 열 어 디 버 깅 을 한 결과 springMVC 용기 의 요청 이 구체 적 인 contrller 에 반영 되 지 않 은 것 같 습 니 다.
설정 방식 B, 다음 과 같 음:
효 과 를 빠르게 검증 하기 위해 < context: component - can base - package = "com. test" / > 스 캔 을 applicationContext - MVC. xml 에 설정 하고 재 부팅 후 검증 에 성 공 했 습 니 다. springMVC 점프 가 유효 합 니 다.
구체 적 인 원인 을 보 려 면 원본 코드 를 뒤 져 보 세 요. springMVC 의 Dispatcher Servlet 부터 보 세 요. 요청 이 들 어 온 후에 무슨 일이 일 어 났 습 니까? 길 게 살 펴 본 후에 원인 을 찾 으 면 다음 과 같 습 니 다.
springMVC 초기 화 시 현재 용기 에 있 는 모든 @ Controller 주해 빈 을 찾 아 handler 인지 확인 합 니 다. 현재 용기 springMVC 에 등 록 된 빈 에는 @ Controller 주해 가 없습니다. 위 에서 언급 한 설정 방식 A, 모든 @ Controller 설정 빈 은 Spring 이라는 부모 용기 에 등록 되 어 있 습 니 다. 코드 를 보십시오.
protected void initHandlerMethods() {
        if (logger.isDebugEnabled()) {
            logger.debug("Looking for request mappings in application context: " + getApplicationContext());
        }

        String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?
                BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
                getApplicationContext().getBeanNamesForType(Object.class));

        for (String beanName : beanNames) {
            if (isHandler(getApplicationContext().getType(beanName))){
                detectHandlerMethods(beanName);
            }
        }
        handlerMethodsInitialized(getHandlerMethods());
    }

방법 isHandler 에서 현재 bean 의 주석 이 controller 인지 여 부 를 판단 합 니 다. 코드 는 다음 과 같 습 니 다.
protected boolean isHandler(Class<?> beanType) {
        return AnnotationUtils.findAnnotation(beanType, Controller.class) != null;
    }

설정 방식 B 에는 springMVC 용기 에 @ Controller 주해 빈 이 모두 포함 되 어 있어 자 연 스 럽 게 찾 을 수 있 습 니 다.
이상 이 원인 입 니 다. 해결 방법 은 무엇 입 니까? initHandler Methods () 를 주의 깊 게 보 세 요.방법 중 detectHandlerMethodsInAncestor Contexts 이 스위치 는 부모 용 기 를 포함 하 는 지 여 부 를 가 져 오 는 것 을 주로 제어 합 니 다. 기본 값 은 포함 되 지 않 습 니 다. 따라서 해결 방법 은 있 습 니 다. 즉, springMVC 설정 파일 에 HandlerMapping 의 detectHandlerMethodsInAncestor Contexts 속성 을 true 로 설정 하면 됩 니 다.부모 용기 의 bean 을 검사 할 수 있 도록 구체 적 인 항목 에 따라 어떤 Handler Mapping 을 사용 하 는 지 확인 해 야 합 니 다. 다음 과 같 습 니 다.
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
        <property name="detectHandlerMethodsInAncestorContexts">
            <value>true</value>
        </property>
    </bean>

이상 은 이미 두 가지 해결 방안 이 있 지만 실제 공사 에 서 는 많은 설정 을 포함 하고 서로 다른 업무 모듈 에 따라 구분 하기 때문에 우 리 는 일반적으로 각자 책임 을 지고 경 계 를 명 확 히 하 는 것 이 생각 입 니 다. Spring 뿌리 용 기 는 다른 contrller 가 아 닌 Bean 의 등록 을 책임 지고 SpringMVC 는 contrller 와 관련 된 Bean 의 등록 만 책임 집 니 다. 세 번 째 방안 은 다음 과 같 습 니 다.
Spring 용기 설정, 모든 @ controller 의 Bean 제거
<context:component-scan base-package="com.fsnip.open">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

SpringMVC 용기 설정, @ controller 의 Bean 만 포함 하도록 합 니 다.
<context:component-scan base-package="com.fsnip.open" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
    </context:component-scan>

개인 적 으로 세 번 째 방안 을 추천 합 니 다. 프로젝트 에서 사 무 를 사용 하 는 배치 방안 도 이런 장면 에서 효력 을 잃 을 수 있 습 니 다. 결국 두 용기 의 가시 적 인 문제 로 인해 구체 적 인 문 제 를 결합 하여 위의 사고 에 따라 원인 을 찾 을 수 있 습 니 다! (- 전문 완성 -)
스프링 과 스프링 MVC 의 용기 관계 분석

좋은 웹페이지 즐겨찾기