2009-07-06 21 views
8

私はSpringを使用して、一部のリモートサーバへのRMI呼び出しを処理しています。アプリケーションコンテキストを構築し、クライアントからリモート呼び出しのための豆を得ることは簡単です。Springコンテキストへのプロパティの受け渡し

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

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

私は設定にプロパティを渡すための簡単な方法が表示されませんが。たとえば、クライアント内の実行時にリモートサーバーのホスト名を特定する場合などです。

私は、理想的には、このようなSpringコンテキスト内のエントリがあるだろう:

<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を使用してこれらのプロパティを置き換えることはできますが、これはファイルから読み取られたプロパティに対してのみ機能することがわかります。

これを解決する実装があります(答えとして追加されました)が、私は自分自身を回避するための標準Spring実装を探しています。設定を初期化するために別のSpringコンフィグラ(または何か)があるのですか、これを達成するためにJava設定を調べる方が良いでしょうか?

+0

? –

+0

クライアントは任意のサーバーに接続できます。ユーザーはテキストフィールドにホスト名を入力できます。したがって、コンパイル時に決定されません。 –

答えて

1

更新

質問の更新に基づいて、私の提案は次のとおりです。

  1. は、クライアントの入力に基づいて処理する必要があるものは何でも扱うServiceResolver Beanを作成します。
  2. このBeanを関連するサービスへの依存として宣言します。
  3. 実行時に、このBeanを更新/使用しても問題ありません。

ServiceResolverでき、その後、いずれかの例えばに基づいて、クライアントに返す値を決定init-methodまたは各呼び出しでJNDIルックアップまたは環境変数。

しかし、これを行う前に、configuration optionsをご覧ください。

  • コンパイル時に存在しなくてもよいプロパティファイルを追加します。
  • JNDIから値を検索します。
  • System.propertiesから値を取得します。カスタム場所からプロパティを参照する必要がある場合は

は、org.springframework.beans.factory.config.BeanFactoryPostProcessorを見てみるとorg.springframework.beans.factory.config.PropertyPlaceholderConfigurerがどのように実装されています。

基本的な考え方は、 'raw'プロパティを持つBeanを取得することです。 ${jdbcDriverClassName}を入力して解決し、目的の値に置き換えます。

+0

これは私の既存の実装がどのようにそれを行うのか、それを反映するために私の質問を更新します。私はこのために標準的な春の実装があることを望んでいたので、私は自分自身を圧延することを避けることができます。 –

1

PropertyPlaceholderConfigurerはファイルからプロパティを取得できますが、それが見つからない場合はシステムプロパティを使用することに戻ります。これはクライアントアプリケーションの実行可能なオプションのように聞こえますが、クライアントを起動するときに-Dを使用してシステムプロパティを渡すだけです。それは 指定されたプロパティのいずれかとプレースホルダを解決できない場合

javadoc

から構成器はまた システムプロパティ(例えば「はuser.dir」)に対してチェックされます。この は "systemPropertiesMode"でカスタマイズできます。

2

既存のソリューションでは、Mapを追加のコンストラクタ引数として受け取る新しいMapAwareApplicationContextを定義します。

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

    return bean; 
} 
:MapAwareインタフェースを実装する任意の型にマップを注入する

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

MapAwareProcessorは(postProcessBeforeInitializationを実装):

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に追加するためにオーバーライド

次に、私の設定に新しいBeanを追加してMapAwarePropertyPlaceholderConfigurerを宣言します:

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

コンフィギュレータはMapAwareを実装しているため、上記のようにMapがインジェクトされます。これは、親コンフィギュラにマップ、または代理人からプロパティを解決するために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; 
} 
+1

良い主人、それは単純な問題の複雑な解決策です... – skaffman

+0

これは私の主張のようなものです。あまりにも多くの努力を要することなく、これ以上の努力をしなくてはならないもののようです。 –

+0

または、BeanFactoryPostProcessorを使うことができます:http://springindepth.com/book/in-depth-ioc-bean- post-processors-and-beanFactory-post-processors.html – Talijanac

0

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(); 
13

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 
関連する問題