Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/366.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 将属性传递给Spring上下文_Java_Spring_Rmi - Fatal编程技术网

Java 将属性传递给Spring上下文

Java 将属性传递给Spring上下文,java,spring,rmi,Java,Spring,Rmi,我正在使用Spring处理对某个远程服务器的RMI调用。构造应用程序上下文并从客户机中获取用于远程调用的bean非常简单: ApplicationContext context = new ApplicationContext("classpath:context.xml"); MyService myService = (MyService ) context.getBean( "myService " ); 但是,我没有看到将属性传递到配置中的简单方法。例如,如果我想在客户端运行时确定远

我正在使用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>

并将属性作为参数从客户端传递到上下文

我可以在上下文中使用PropertyPlaceHolderConfigure来替换这些属性,但据我所知,这只适用于从文件读取的属性

我有一个解决这个问题的实现(作为一个答案添加),但我正在寻找一个标准的Spring实现,以避免我自己的实现。是否有其他Spring配置程序(或其他任何东西)来帮助初始化配置,或者我最好通过查看java配置来实现这一点?

更新:

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

  • 创建一个
    servicesolver
    bean,它根据客户端输入处理您需要处理的任何事情
  • 将此bean声明为相关服务的依赖项
  • 在运行时,您可以按照自己认为合适的方式更新/使用这个bean
  • 然后,
    servicesolver
    可以在
    init方法上,或者在每次调用时,根据JNDI查找或环境变量,确定要返回给客户端的值

    但是在做这件事之前,您可能想看看可用的。您可以:

    • 添加不必在编译时出现的属性文件
    • 从JNDI中查找值
    • 从System.properties中获取值

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


    基本思想是,您获得具有“原始”属性的bean,例如,
    ${jdbcdrivercassname}
    ,然后您可以解析它们并用所需的值替换它们。

    propertyplaceholderconfigure可以从文件中获取属性,这是正确的,但如果找不到它们,它会使用系统属性。对于您的客户机应用程序来说,这似乎是一个可行的选项,只需在启动客户机时使用-D传递系统属性即可

    配置程序还将检查 系统属性(例如“user.dir”),如果 它无法使用解析占位符 任何指定的属性。这 可通过 “系统属性模式”


    我现有的解决方案涉及定义一个新的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();
    }
    
    MapawareReprocessor实现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添加到我的配置中,以声明MapawarepropertyPlaceHolderConfigure:

    <bean id="propertyConfigurer"
      class="com.hsbc.r2ds.spring.MapAwarePropertyPlaceholderConfigurer"/>
    
    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;
    }
    

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

    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;
        }
    }
    
    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());
        }
    }
    
    SpringStart.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;
        }
    }
    
    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

    
    
    输出:

    第一个值
    第二值
    

    您还可以将属性存储在哪里?客户端可以连接到任何服务器,例如,用户可以在文本字段中键入主机名。所以它不是在编译时确定的。感谢我现有的实现就是这样做的,我将更新我的问题以反映这一点。我希望有一个标准的Spring实现来实现这一点,这样我就可以避免使用我自己的。这就是我的观点,这似乎是不需要太多努力就可以实现的,当然也不需要太多努力,或者你可以使用BeanFactoryPostProcessor: