9

Springを使用してリモートサーバーへのRMI呼び出しを処理しています。アプリケーションコンテキストを構築し、クライアント内からリモート呼び出し用のBeanを取得するのは簡単です。

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実装を探しています。構成を初期化するのに役立つ別のSpringconfigurer(または他のもの)はありますか、それともこれを達成するためにJava構成を調べる方が良いですか?

4

5 に答える 5

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
于 2010-02-03T15:25:35.550 に答える
2

私の既存のソリューションには、追加のコンストラクター引数として Map を取る新しい 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 は postProcessBeforeInitialization() を実装して、MapAware インターフェイスを実装する任意の型にマップを挿入します。

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

    return bean;
}

次に、構成に新しい 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;
}
于 2009-07-06T10:10:08.167 に答える
1

更新

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

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

次にServiceResolverinit-method呼び出し時または呼び出しごとに、JNDI ルックアップや環境変数などに基づいて、クライアントに返す値を決定できます。

ただし、その前に、利用可能な構成オプションを確認することをお勧めします。次のいずれかを実行できます。

  • コンパイル時に存在する必要のないプロパティ ファイルを追加します。
  • JNDI から値を検索します。
  • System.properties から値を取得します。

カスタムの場所からプロパティを検索する必要がある場合は、実装org.springframework.beans.factory.config.BeanFactoryPostProcessor方法を参照してください。org.springframework.beans.factory.config.PropertyPlaceholderConfigurer

基本的な考え方は、「生の」プロパティを持つ Bean を取得することです。たとえば${jdbcDriverClassName}、それらを解決して目的の値に置き換えることができます。

于 2009-07-06T09:53:10.917 に答える
1

PropertyPlaceholderConfigurer は、ファイルからプロパティを取得できますが、それが見つからない場合は、システム プロパティの使用にフォールバックします。これは、クライアント アプリケーションの実行可能なオプションのように思えます。クライアントを起動するときに -D を使用してシステム プロパティを渡すだけです。

javadocから

コンフィギュアラーは、指定されたプロパティのいずれかでプレースホルダーを解決できない場合、システム プロパティ ("user.dir" など) に対してもチェックします。これは、「systemPropertiesMode」でカスタマイズできます。

于 2009-07-06T10:00:39.607 に答える
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();
于 2009-07-06T13:04:27.447 に答える