代码之家  ›  专栏  ›  技术社区  ›  Rich Seller

将属性传递给Spring上下文

  •  9
  • Rich Seller  · 技术社区  · 16 年前

    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>
    

    5 回复  |  直到 14 年前
        1
  •  1
  •   Robert Munteanu    16 年前

    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
    
        2
  •  13
  •   Tunaki    9 年前

    我现有的解决方案涉及定义一个新的MapAwareApplicationContext,该上下文将Map作为额外的构造函数参数。

    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()以添加MapAwardProcessor:

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

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

    然后,我将一个新的bean添加到我的配置中,以声明一个MapAwardProperties占位符配置器:

    <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;
    }
    
        3
  •  2
  •   Rich Seller    16 年前

    更新 :

    根据问题更新,我的建议是:

    1. 创建一个 ServiceResolver bean,它根据客户端输入处理您需要处理的任何内容;
    2. 将此bean声明为对相关服务的依赖;
    3. 在运行时,您可以根据需要更新/使用此bean。

    服务解析器 然后,可以在 init-method 或者在每次调用时基于例如JNDI查找或环境变量确定要返回给客户端的值。

    但在这样做之前,你可能想看看 configuration options 可用。您可以:

    • 添加编译时不必存在的属性文件;

    如果需要从自定义位置查找属性,请查看 org.springframework.beans.factory.config.BeanFactoryPostProcessor 以及如何 org.springframework.beans.factory.config.PropertyPlaceholderConfigurer 实施。

    基本思想是,你得到的豆子具有“生”的特性,例如。 ${jdbcDriverClassName} 然后,您可以解决这些问题,并用所需的值替换它们。

        4
  •  1
  •   skaffman    16 年前

    PropertyPlaceholderConfigurer可以从文件中获取属性,这是真的,但如果找不到它们,它就会退回到使用系统属性。对于您的客户端应用程序来说,这听起来是一个可行的选择,只需在启动客户端时使用-D传递系统属性即可。

    javadoc

    系统属性(例如“user.dir”)如果 它无法解析占位符 任何指定的属性。这 可以通过以下方式定制 “系统属性模式”。

        5
  •  0
  •   Chin Huang    16 年前

    创建 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();