문제

스프링을 사용하여 일부 원격 서버로 RMI 호출을 처리합니다. 응용 프로그램 컨텍스트를 구성하고 클라이언트 내에서 원격 호출에 대한 Bean을 얻는 것이 간단합니다.

ApplicationContext context = new ApplicationContext("classpath:context.xml");

MyService myService = (MyService ) context.getBean( "myService " );

그러나 속성을 구성에 전달하는 간단한 방법은 보이지 않습니다. 예를 들어 클라이언트 내에서 런타임에 원격 서버의 호스트 이름을 결정하려면

나는 이상적으로 다음과 같은 스프링 컨텍스트에 항목을 가지고 있습니다.

<bean id="myService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
  <property name="serviceUrl" value="rmi://${webServer.host}:80/MyService"/>
  <property name="serviceInterface" value="com.foo.MyService"/>
</bean>

클라이언트의 컨텍스트로 속성을 매개 변수로 전달하십시오.

맥락에서 PropertyPlaceHolderConfigurer를 사용할 수 있으며 이러한 속성을 대체 할 수 있지만,이 말을 할 수있는 한 파일에서 읽은 속성에 대해서만 작동합니다.

이 문제를 해결하는 구현 (답으로 추가)이 있지만 내 자신의 롤을 피하기 위해 표준 스프링 구현을 찾고 있습니다. 구성을 초기화하는 데 도움이되는 또 다른 스프링 구성 (또는 다른)이 있습니까? 아니면이를 달성하기 위해 Java 구성을 보는 것이 좋습니다.

도움이 되었습니까?

해결책

업데이트:

질문 업데이트를 기반으로 내 제안은 다음과 같습니다.

  1. a ServiceResolver 클라이언트 입력에 따라 처리해야 할 모든 것을 처리하는 Bean;
  2. 이 Bean을 관련 서비스에 대한 종속성으로 선언하십시오.
  3. 런타임 에서이 콩을 업데이트 / 사용할 수는 있지만 적합하다고 생각합니다.

그만큼 ServiceResolver 그러면 init-method 또는 각 호출에서 예를 들어 JNDI 조회 또는 환경 변수에 따라 클라이언트로 돌아갈 값을 결정합니다.

그러나 그렇게하기 전에, 당신은 구성 옵션 사용 가능. 당신은 둘 중 하나를 할 수 있습니다 :

  • 컴파일 타임에 존재할 필요가없는 속성 파일을 추가하십시오.
  • JNDI의 값을 찾아보십시오.
  • System.properties에서 값을 얻습니다.

사용자 정의 위치에서 속성을 조회 해야하는 경우 살펴보십시오. org.springframework.beans.factory.config.BeanFactoryPostProcessor 그리고 어떻게 org.springframework.beans.factory.config.PropertyPlaceholderConfigurer 구현되었습니다.

기본 아이디어는 '원시'특성으로 콩을 얻는 것입니다. ${jdbcDriverClassName} 그런 다음 해결하고 원하는 값으로 교체 할 수 있습니다.

다른 팁

보다 http://forum.springsource.org/showthread.php?t=71815

TestClass.java

package com.spring.ioc;

public class TestClass {

    private String first;
    private String second;

    public String getFirst() {
        return first;
    }

    public void setFirst(String first) {
        this.first = first;
    }

    public String getSecond() {
        return second;
    }

    public void setSecond(String second) {
        this.second = second;
    }
}

SpringStart.java

package com.spring;

import java.util.Properties;

import com.spring.ioc.TestClass;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;

public class SpringStart {
    public static void main(String[] args) throws Exception {
    PropertyPlaceholderConfigurer configurer = new PropertyPlaceholderConfigurer();
    Properties properties = new Properties();
    properties.setProperty("first.prop", "first value");
    properties.setProperty("second.prop", "second value");
    configurer.setProperties(properties);

    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext();
    context.addBeanFactoryPostProcessor(configurer);

    context.setConfigLocation("spring-config.xml");
    context.refresh();

    TestClass testClass = (TestClass)context.getBean("testBean");
    System.out.println(testClass.getFirst());
    System.out.println(testClass.getSecond());
    }
}

spring-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean id="testBean" class="com.spring.ioc.TestClass">
        <property name="first" value="${first.prop}"/>
        <property name="second" value="${second.prop}"/>
    </bean>

</beans>

산출:

first value
second value

내 기존 솔루션에는 추가 생성자 인수로 맵을 취하는 새로운 MapaWareApplicationContext를 정의하는 것이 포함됩니다.

public MapAwareApplicationContext(final URL[] configURLs,
    final String[] newConfigLocations,
    final Map<String, String> additionalProperties) {
    super(null);

    //standard constructor content here

    this.map = new HashMap<String, String>(additionalProperties);

    refresh();
}

postprocessbeanfactory ()를 무시하여 mapawareprocessor를 추가합니다.

protected void postProcessBeanFactory(
    final ConfigurableListableBeanFactory beanFactory) {
    beanFactory.addBeanPostProcessor(new MapAwareProcessor(this.map));
    beanFactory.ignoreDependencyInterface(MapAware.class);
}

Mapawareprocessor는 후 프로세스 후 전신 인니티브 화 ()를 구현하여 Mapaware 인터페이스를 구현하는 모든 유형에 맵을 주입합니다.

public Object postProcessBeforeInitialization(final Object bean, 
        final String beanName) {
    if (this.map != null && bean instanceof MapAware) {
        ((MapAware) bean).setMap(this.map);
    }

    return bean;
}

그런 다음 구성에 새 콩을 추가하여 MapaWarePropertyplaceholderConfigurer를 선언합니다.

<bean id="propertyConfigurer"
  class="com.hsbc.r2ds.spring.MapAwarePropertyPlaceholderConfigurer"/>

구성자는 MapaWare를 구현하므로 위와 같이 맵이 주입됩니다. 그런 다음 ResolvePlaceHolder ()를 구현하여지도에서 속성을 해결하거나 부모 구성 자에게 위임합니다.

protected String resolvePlaceholder(final String placeholder, 
        final Properties props, final int systemPropertiesMode) {
    String propVal = null;
    if (this.map != null) {
        propVal = this.map.get(placeholder);
    }
    if (propVal == null) {
        propVal = super.resolvePlaceholder(placeholder, props);
    }
    return propVal;
}

PropertyPlaceHolderConfigurer는 파일에서 속성을 가져올 수 있습니다. 사실이지만, 찾을 수 없다면 시스템 속성 사용으로 돌아갑니다. 이는 클라이언트 응용 프로그램을위한 실행 가능한 옵션처럼 들리며 클라이언트를 시작할 때 -D를 사용하여 시스템 속성을 전달하십시오.

로부터 Javadoc

구성자는 지정된 속성으로 자리 표시자를 해결할 수없는 경우 시스템 속성 (예 : "User.Dir")에 대해서도 확인합니다. "SystemPropertiesMode"를 통해 사용자 지정할 수 있습니다.

생성 RmiProxyFactoryBean 인스턴스 및 구성 serviceUrl 코드의 직접 속성 :

String serverHost = "www.example.com";

RmiProxyFactoryBean factory = new RmiProxyFactoryBean();
factory.setServiceUrl("rmi://" + serverHost + ":80/MyService");
factory.setServiceInterface(MyService.class);
try {
    factory.afterPropertiesSet();
} catch (Exception e) {
    throw new RuntimeException(
            "Problem initializing myService factory", e);
}
MyService myService = (MyService) factory.getObject();
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top