2011-03-02 3 views
31

현재 스프링 3.1.0.M1을 기반으로하는 웹 응용 프로그램에서 주석을 기반으로 작업하며 응용 프로그램의 특정 위치에서 속성 자리 표시 자 해결과 관련된 문제가 있습니다.스프링에서 프로퍼티 자리 표시자를 프로그래밍 방식으로 해결하는 방법

다음은 이야기입니다. (내가

MVC-config.xml에 있습니다) DispatcherServlet에 의해로드 내 웹 응용 프로그램의 맥락에서

1) :

<!-- Handles HTTP GET requests for /resources/version/** --> 
<resources mapping="/${app.resources.path}/**" location="/static/" cache-period="31556926"/> 

... 

<!-- Web properties --> 
<context:property-placeholder location=" 
    classpath:app.properties 
    "/> 

2) 내부 app.properties를,이 속성은 다른 사람의 사이가 :

app.properties :

# Properties provided (filtered) by Maven itself 
app.version: 0.1-SNAPSHOT 
... 

# Static resources mapping 
app.resources.path: resources/${app.version} 

3) 내 JS에서 JSP 사용자 정의 태그를 P 2.1 템플릿. 이 태그는 환경 설정, 앱 버전, 봄 테마 선택 등에 따라 전체 리소스 경로를 생성합니다. 맞춤 태그 클래스는 봄 : URL 구현 클래스를 확장하므로 일반적인 URL 태그로 간주 될 수 있지만 적절한 경로에 대한 추가 지식이 있습니다.

내 문제는 내 JSP 사용자 정의 태그 구현에서 $ {app.resources.path}를 올바르게 해석 할 수 없다는 것입니다. JSP 커스텀 태그는 Spring이 아닌 서블릿 컨테이너에 의해 관리되므로 DI에 참여하지 않아야한다. 그래서 나는 보통의 @Value ("$ {app.resources.path}")를 사용할 수없고 Spring에 의해 자동적으로 해결된다.

나는 웹 응용 프로그램 컨텍스트 인스턴스가 있으므로 프로그래밍 방식으로 내 속성을 해결해야합니다.

는 지금까지 시도 :

ResourceTag.java :

// returns null 
PropertyResolver resolver = getRequestContext().getWebApplicationContext().getBean(PropertyResolver.class); 
resolver.getProperty("app.resources.path"); 


// returns null, its the same web context instance (as expected) 
PropertyResolver resolver2 = WebApplicationContextUtils.getRequiredWebApplicationContext(pageContext.getServletContext()).getBean(PropertyResolver.class); 
resolver2.getProperty("app.resources.path"); 


// throws NPE, resolver3 is null as StringValueResolver is not bound 
StringValueResolver resolver3 = getRequestContext().getWebApplicationContext().getBean(StringValueResolver.class); 
resolver3.resolveStringValue("app.resources.path"); 


// null, since context: property-placeholder does not register itself as PropertySource 
Environment env = getRequestContext().getWebApplicationContext().getEnvironment(); 
env.getProperty("app.resources.path"); 

그래서 지금은 좀 그와 함께 붙어있어. 내 자리 표시자를 해결할 수있는 능력이 문맥에 어딘가에 있다는 것을 알고 있습니다. 올바른 방법을 모릅니다.
확인할 수있는 도움이나 아이디어가 있으면 감사하겠습니다. 이 같은 특성을 :

<util:properties id="appProperties" location="classpath:app.properties" /> 

및 코드에서, 다음과 같이 사용 :

답변

13

제가 생각하기보다는 상황에 맞는 장소 홀더의 내부 작업에 초점을 맞추고, 당신은 단순히 새로운 폴더의 유틸리티를 정의 할 수 있습니다

Properties props = appContext.getBean("appProperties", Properties.class); 

또는 이런 식으로 당신이 할 수있는 곳 DI :

또 하나 개의 가능한 솔루션이 있습니다
@Value("#{appProperties['app.resources.path']}") 
+0

감사합니다. Ritesh. 나는이 솔루션을 사용할 수 있다고 생각한다. –

+0

이 답변을 수락 됨으로 표시했지만, 순수 프로그래밍 방식 솔루션을 찾는 것은 흥미 롭습니다. –

+0

@Max Alexejev PropertyPlaceholderConfigurer를 확장하고 processProperties 메서드에 두 번째 인수로 전달 된 해결 된 속성을 캡처 할 수도 있습니다. 그러나 context 대신 context-bean을 사용해야한다. – Ritesh

1

: 만들 태그 제공자 라이선스 계약 AspectJ를 통해 @Configurable하고 컴파일 타임이나 로딩 타임을 가능하게한다. 그런 다음 커스텀 태그에서 일반적인 @Value 주석을 사용할 수 있습니다. 하지만, 실제로 저는 두 개의 클래스로 인해 인프라를 짜고 싶지 않습니다. 여전히 ApplicationContext를 통해 자리 표시자를 해결하는 방법을 찾고 있습니다.

23

버전 3.0부터 스프링은 beanFactory에 문자열 분석기 목록을 유지합니다. 당신은 다음과 같이 사용할 수 있습니다 : 주석 그래서 어쩌면 우리는 그 사용을 우회하는 속성과 같은 포함 된 값을 해결하기위한로

String value = appContext.getBeanFactory().resolveEmbeddedValue("${prop}"); 

javadoc의 상태에이 방법을하지만 작동합니다.

+0

대단히 감사합니다! 환경을 쿼리 할 수있는 확실한 방법을 찾고있었습니다. –

30

봄 3.0.3 이후 appContext.getBeanFactory().resolveEmbeddedValue("${prop}") 호출을 사용하는 다른 게시물에서 언급 한 것과 같은 방식으로 작동하는 EmbeddedValueResolverAware가 있습니다.

문제 해결하려면

  1. 이 EmbeddedValueResolverAware 인터페이스를 구현하는 클래스를 확인을하면 해결은 코드와 같이 당신이 속성을 검색 할 수 있습니다 어디 그럼 당신

  2. 위해 주입 얻을 것이다 미리보기 :

    String propertyValue = resolver.resolveStringValue("${your.property.name}"); 
    
    그런

당신 BE 필요로하는 프로퍼티를 얻기 위해 ApplicationContext에 의존 할 필요는 없다.

+3

이것은 문제를 해결하는 매우 간단한 방법입니다. 미래의 모든 독자를 위해 프로그래밍 방식으로 속성을 해결하고 setter 메서드를 구현하고 @Eds가 작성한 코드를 사용하여 해결할 수있게하려는 봄 관리 클래스에 EmbeddedValueResolverAware 인터페이스를 추가하기 만하면됩니다. – Alex

+0

사실 알렉스는 그의 코멘트에 대해 엄지 손가락을받을 가치가있다. 답을 편집하고 싶지 않으십니까? – Heri

+0

이것은 여러 스프링 애플리케이션에서 작동해야하는 공유 구성 요소/구성을 작성하는 데 적합하다고 생각한 유일한 접근 방법입니다. 이 코드가 특정 앱이 파일 또는 다른 방법을 통해 속성 설정을 가져 오는 방법에 의존하지 않도록하려는 경우. –

4

하나의 옵션은 ConfigurableEnvironment에 (인 - 메모리 구성을 예시하기 위해 여기 MapPropertySource)는 PropertySource를 추가하고 속성을 해결하기를 요청하는 것입니다.

public class Foo { 

    @Autowired 
    private ConfigurableEnvironment env; 

    @PostConstruct 
    public void setup() { 
     env.getPropertySources() 
      .addFirst(new MapPropertySource("my-propertysource", 
       ImmutableMap.<String, Object>of("your.property.name", "the value"))); 
     env.resolvePlaceholders("your.property.name"); 
    } 
} 

는 선택적으로 XML 찬성 프로그램 구성의 힘을 즐길 수 @Configuration으로 Foo 클래스를 주석을 달 수 있습니다.

관련 문제