Java 如何获取前缀为“abc”的所有属性。来自 PropertyPlaceholderConfigurer

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20796882/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 04:23:55  来源:igfitidea点击:

How can I get all properties with prefix 'abc.' from PropertyPlaceholderConfigurer

javaspringproperties

提问by Freewind

In spring context file, I use org.springframework.beans.factory.config.PropertyPlaceholderConfigurerto load several configuration files:

在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>

The a.properties, b.properties, c.propertesmay have some hibernate configurations which have prefix of abc.:

a.propertiesb.propertiesc.propertes可能具有的前缀一些休眠的配置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

Now I want to define a hibernate session factory:

现在我想定义一个休眠会话工厂:

<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>

You can see I have to write the property in bean declaration again and again:

你可以看到我必须一次又一次地在 bean 声明中写入属性:

<prop key="hibernate.xxx">${abc.hibernate.xxx}</prop>

Is there any way to just tell spring to get all properties which have prefix abc.?

有什么方法可以告诉 spring 获取所有具有前缀的属性abc.吗?

So I can write:

所以我可以写:

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="hibernateProperties">
        <something prefix="abc" /> <!-- TODO -->
    </property>
</bean>

Is it possible or is there any other simple solutions for it?

是否有可能或是否有其他简单的解决方案?

回答by Vlad

You can use something like the following class to extend java.util.Properties:

您可以使用类似于以下类的内容来扩展 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);
            }
        }
    }    
}

Then you can define sessionFactory as following:

然后你可以定义 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>

I don't see any other possibility to filter properties.

我看不到任何其他过滤属性的可能性。

回答by Sean Patrick Floyd

The PropertyPlaceHolderConfigureris a special construct that is meant for bean creation only. It does not expose the underlying properties in a way that you can access.

PropertyPlaceHolderConfigurer是一个特殊的构造,仅用于创建 bean。它不会以您可以访问的方式公开底层属性。

A possible workaround is to subclass PropertyPlaceHolderConfigurer, as I have outlined in a previous answer of mine.

一种可能的解决方法是子类化PropertyPlaceHolderConfigurer正如我在我之前的回答中概述的那样

Another way is to have a custom PropertiesFactoryBean, like this one:

另一种方法是使用自定义 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;
    }
}

You can use this in your XML as follows:

您可以在您的 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>

This is of course redundant, as you'd probably still have to wire the PropertyPlaceHolderConfigurerto set up your other beans.

这当然是多余的,因为您可能仍然需要连接PropertyPlaceHolderConfigurer来设置其他 bean。

回答by Jose Luis Martin

As Sean said, PropertyPlaceHolderConfigurerdon't expose his properties, but you could use reflection to filter them.

正如肖恩所说,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;
    }

And inject with 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>