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