복붙노트

[SPRING] Spring @Value가 @Controller와 호환되지 않는 이유는 무엇입니까?

SPRING

Spring @Value가 @Controller와 호환되지 않는 이유는 무엇입니까?

이 문제를 더 잘 이해하고 싶습니다. 해결 방법은 매우 간단합니다. 즉, 구성 데이터를 프록시 / 어드바이스가없는 다른 클래스로 이동 시키십시오. 그러나 이것을 이해하면 나중에 다른 관련 문제가 발생하지 않도록 도움이 될 것입니다. 제공 할 수 있습니다.

스프링 STS 및 vFabric tc 서버와 함께 Spring 3.1.0.RELEASE를 사용하고 있습니다. @Controller 클래스를 사용하여 기본적인 REST 서버를 구현했다. 그 모든 것이 훌륭하지만 (실제로는 그렇습니다), @Controller 또한 @Transactional이며,로드 시간 짜기와 vFabric tc 서버 사이에 @Value가 나옵니다.

@Controller
@RequestMapping("/hello")
public class MyAPI {

    @Value("${my.property}")
    private String prop;
    ...

    @Transactional
    handleRequest(...) ...


}

그리고 속성 파일 app.properties :

my.property = SUCCESS

이것은 JUnit에서 제대로 작동합니다. 테스트에서 "SUCCESS"로 설정된 소품이있는 MyAPI 객체를 얻습니다. 그러나 앱이 vFabric에로드되면로드 시간과 프록시를 가져 오는 것으로 생각됩니다. 어떤 일이 생기더라도 prop == "SUCCESS"를 가진 두 개의 MyAPI 인스턴스와 prop == "$ {my.prop}"을 가진 또 다른 인스턴스 (http 요청을 처리하는 인스턴스)가 만들어집니다.

그래서 all-in-all은 이것을 AOP 같은 것을 사용하는 것에 대한 나의 가장 큰 관심사 인 마법의 실패라고합니다. STS로도 문제의 원인이 무엇인지 추적하거나 심각한 버그인지 파악할 수 없습니다. 그것이 버그라면 Spring, AspectJ,로드 타임 위버 또는 vFabric의 버그인지 여부를 알 수 없으므로 버그 리포트를 제출할 위치조차 모른다.

그래서 이것을 이해하는 데 도움이 될 것입니다. 감사.

해결법

  1. ==============================

    1.나는 그것을 알아. 정말로, 그것은 너무 많은 마술이었다.

    나는 그것을 알아. 정말로, 그것은 너무 많은 마술이었다.

    STS에서 Spring Roo를 사용하여 기본 응용 프로그램 프레임 워크를 생성 한 다음 STS를 사용하여 Roo를 분해했습니다.

    Roo가 "모범 사례"로 수행하는 한 가지 방법은 두 개의 Spring 컨텍스트를 만드는 것입니다. 하나는 전체 응용 프로그램이고 하나는 Dispatcher 서블릿으로 제한됩니다. 정확히 왜, 아직까지는 얻지 못했지만 컨트롤러와 같은 프리젠 테이션 레이어가 공유되는 서비스 레이어로 들어오지 못하게하려고합니다. 이것은 axtavt에 의해 잘 설명되었습니다. 이것은 모두 STS에 의해 숨겨져있었습니다.

    Roo를 사용하는 STS에서 WEB-INF 소스는 / src / main / resources (META-INF 디렉토리가있는 곳)에 있지만 대신에 / src / main / webapp 아래에 있습니다. 원본 디렉토리이므로 / target 디렉토리 바로 위에 완전히 따로 표시되므로 출력 폴더를 잘못 입력했습니다.

    applicationContext.xml에서 Roo는 axtavt의 포스트에서 설명한 것처럼 애플리케이션 컨텍스트가 컨트롤러를 생성하지 못하도록 필터를 삽입했지만 Roo가 생성 한 클래스 검색을 제거하는 또 다른 필터를 추가했습니다. 두 필터를 동시에 가져갔습니다. 실제로 무엇을했는지 알지 못했지만 Roo의 나머지 부분이라고 생각했습니다.

    이제 컨트롤러의 문제는 이전에 설명한 것처럼 두 번 만들어졌습니다. applicationContext.xml을 사용하고 속성 파일을 찾기 때문에 응용 프로그램 컨텍스트의 속성은 할당 된 속성을 가져옵니다. 그런데 왜 둘이 속성을 설정하지 않았습니까?

    어느 날 숨겨진 webapps 폴더로 돌아옵니다. WEB-INF 폴더 안에 Roo는 web.xml (자연스럽게)과 webmvc-config.xml 파일이 들어있는 스프링 폴더를 배치했습니다. 이 구성 파일은 컨트롤러를 스캔, 생성 및 설정하도록 설정되었습니다. web.xml 파일은 applicationContext.xml과 dispatcherServlet을 사용하여 webmvc-config.xml을 사용하도록 웹 응용 프로그램을 설정하므로 applicationContext.xml에 필터를 두어 두 번 생성되지 않도록해야합니다.

    퍼즐의 마지막 부분은이 webmvc-config.xml 파일입니다. 이것이 콘트롤러가 설정되는 콘텍스트이기 때문에 그 파일은 프로퍼티 파일을 찾을 수 있도록 를 구성해야했습니다.

  2. ==============================

    2.첫째, $를 사용하는 표기법은 정확하고 #

    첫째, $를 사용하는 표기법은 정확하고 #

    이제는 원래의 포스터와 관련하여 두 주석 (@Controller와 @Transactional) 사이에 상반되는 행동이 있다고 생각합니다.

    @Transactional 어노테이션을 사용하면 구현을 촉진 할 수 있습니다 (오류를 감지하고 롤백을 시작하는 것 같습니다).

    이제 컨트롤러의 인스턴스가 2 개 있다는 것을 알 수 있습니다. 그렇게해서는 안됩니다. 일반적으로 컨트롤러에 하나의 인스턴스 만 메모리에로드해야합니다.

    구성 파일과 관련이있을 수 있습니까? 아니면 @Transactional과 프록시 속성이 있습니까?

    부수적으로, 나는 컨트롤러 자체에서 @Transactional을 사용하지 않았지만 서비스 나 DAO의 방법으로 사용하지 않았다. 실패 할 수 있고 롤백 할 필요가있는 실제 프로세스가 있으므로 다른 컨트롤러 / 소스에서 액세스 할 수 있습니다.

    문안 인사.

  3. ==============================

    3.나는 똑같은 문제가 있었고 그 둘 모두가 필요하다는 사실이었다.

    나는 똑같은 문제가 있었고 그 둘 모두가 필요하다는 사실이었다.

    이 두 가지 시나리오를 작동 시키려면

    이게 도움이 되길 바란다.

    다음은 web.xml입니다.

        <servlet>
        <servlet-name>spring</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:/spring-config/spring-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>spring</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    

    다음은 spring-servlet.xml입니다. 핵심은 두 가지 모두 util : properties 및 context : property-placeholder를 갖는 것입니다. 동일한 파일을 찾더라도 다른 용도로 사용됩니다.

    <util:properties id="propSource" location="classpath:/properties/prop1.properties" />
    <context:property-placeholder location="classpath:/properties/prop1.properties" />
    
    <context:component-scan base-package="com.concurrent.controller" />
    
    <context:annotation-config/>
    <mvc:annotation-driven/> 
    

    다음은 컨트롤러 클래스의 일부입니다.

    @Controller
    @RequestMapping("/fooController")
    public class MyController {
    
    @Value("${message1}")
    public String message1;
    
    @Inject
    public ConfigProperties configProperties;
    

    마지막으로, 여기에 제가 속성을 주입 한 클래스가 있습니다 :

    @Service
    public class ConfigProperties {
    
    @Value("${message1}")
    public String message1;
    }
    

    그건 나를 위해 일했고 당신을 위해 일할 것입니다. 행운을 빕니다!

  4. ==============================

    4.내 경우에는이 방법으로 해결 : Spring-servlet.xml에서 전에 이것을 넣습니다.

    내 경우에는이 방법으로 해결 : Spring-servlet.xml에서 전에 이것을 넣습니다.

    <context:property-placeholder location="classpath:strings.properties"/>
    

    strings.properties 파일은 src / main / resources /에 넣습니다.

    참고 사항 : context : property-placeholder 태그는 가시성이 제한되어 있으므로 문자열을 사용하는 모든 컨텍스트 파일에서이를 복제하는 어딘가 권장 사항을 읽었습니다.

  5. from https://stackoverflow.com/questions/10102216/why-is-spring-value-incompatible-with-controller by cc-by-sa and MIT license