在spring上下文文件中,我使用org.springframework.beans.factory.config.PropertyPlaceholderConfigurer
加载了几个配置文件:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>a.properties</value>
<value>b.properties</value>
<value>c.properties</value>
</list>
</property>
</bean>
a.properties
,b.properties
,c.propertes
可能有一些hibernate配置,前缀为abc.
:
abc.hibernate.show_sql=true
abc.hibernate.default_schema=myschema
abc.hibernate.xxx=xxx
abc.hibernate.xxx=xxx
abc.hibernate.xxx=xxx
abc.hibernate.xxx=xxx
abc.hibernate.xxx=xxx
abc.hibernate.xxx=xxx
现在我要定义一个hibernate会话工厂:
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="hibernateProperties">
<util:properties>
<prop key="hibernate.show_sql">${abc.hibernate.show_sql}</prop>
<prop key="hibernate.xxx">${abc.hibernate.xxx}</prop>
<prop key="hibernate.xxx">${abc.hibernate.xxx}</prop>
<prop key="hibernate.xxx">${abc.hibernate.xxx}</prop>
<prop key="hibernate.xxx">${abc.hibernate.xxx}</prop>
<prop key="hibernate.xxx">${abc.hibernate.xxx}</prop>
</util:properties>
</property>
</bean>
你可以看到我必须一次又一次地在bean声明中编写属性:
<prop key="hibernate.xxx">${abc.hibernate.xxx}</prop>
有没有办法告诉spring获取前缀为abc.
的所有属性?
所以我可以写:
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="hibernateProperties">
<something prefix="abc" /> <!-- TODO -->
</property>
</bean>
是否有可能或有其他简单的解决方案吗?
答案 0 :(得分:4)
您可以使用类似下面的类来扩展java.util.Properties:
import java.util.Enumeration;
import java.util.Properties;
public class PrefixedProperties extends Properties {
public PrefixedProperties(Properties props, String prefix){
if(props == null){
return;
}
Enumeration<String> en = (Enumeration<String>) props.propertyNames();
while(en.hasMoreElements()){
String propName = en.nextElement();
String propValue = props.getProperty(propName);
if(propName.startsWith(prefix)){
String key = propName.substring(prefix.length());
setProperty(key, propValue);
}
}
}
}
然后您可以将sessionFactory定义如下:
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="hibernateProperties">
<bean id="sessionFactoryProperties" class="PrefixedProperties">
<constructor-arg ref="props"/> <!-- reference to all properties -->
<constructor-arg value="abc.hibernate."/> <!-- prefix -->
</bean>
</property>
</bean>
我没有看到任何其他过滤属性的可能性。
答案 1 :(得分:3)
正如肖恩所说,PropertyPlaceHolderConfigurer
没有暴露他的属性,但你可以使用反射来过滤它们。
public static Properties filterProperties(String prefix, PropertyPlaceholderConfigurer ppc) {
Properties props = new Properties();
Method method = ReflectionUtils.findMethod(PropertiesLoaderSupport.class, "mergeProperties");
ReflectionUtils.makeAccessible(method);
Properties all = (Properties) ReflectionUtils.invokeMethod(method, ppc);
for (String key : all.stringPropertyNames()) {
if (key.startsWith(prefix))
props.setProperty(key, all.getProperty(key));
}
return props;
}
注入spel
<bean id="ppc" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
...
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="hibernateProperties" value="#{T(SomeClass).filterProperties('abc.', @ppc)}" />
</bean>
答案 2 :(得分:1)
PropertyPlaceHolderConfigurer
是一个特殊的构造,仅用于创建bean。它不会以您可以访问的方式公开底层属性。
可能的解决方法是继承PropertyPlaceHolderConfigurer
,as I have outlined in a previous answer of mine。
另一种方法是拥有一个自定义的PropertiesFactoryBean,如下所示:
public class PrefixedPropertyFactoryBean extends AbstractFactoryBean<Properties> {
private List<Resource> locations;
public void setLocations(List<Resource> locations) { this.locations = locations; }
private String prefix;
public void setPrefix(String prefix) { this.prefix = prefix; }
@Override public Class<?> getObjectType() { return Properties.class; }
@Override
protected Properties createInstance() throws Exception {
Properties properties = new Properties();
for (Resource resource : locations) {
properties.load( resource.getInputStream());
}
final Iterator<Object> keyIterator = properties.keySet().iterator();
while(keyIterator.hasNext()) {
if(!keyIterator.next().toString().startsWith(prefix))
keyIterator.remove();
}
return properties;
}
}
您可以在XML中使用它,如下所示:
<bean id="hibernateProps" class="some.path.PrefixedPropertyFactoryBean">
<property name="locations">
<list>
<value>a.properties</value>
<value>b.properties</value>
<value>c.properties</value>
</list>
</property>
<property name="prefix" value="abc.hibernate" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="hibernateProperties" ref="hibernateProps" />
</bean>
这当然是多余的,因为您可能仍需要连接PropertyPlaceHolderConfigurer
来设置其他bean。