Özellikler dosyasına programlı olarak erişilsin mi?


137

Aşağıdaki kodu, bir özellik dosyasındaki özelliklere sahip Bahar çekirdeklerini enjekte etmek için kullanıyoruz.

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations" value="classpath:/my.properties"/>
</bean>

<bean id="blah" class="abc">
    <property name="path" value="${the.path}"/>
</bean>

Özelliklere programlı olarak erişebilmemizin bir yolu var mı? Bağımlılık enjeksiyonu olmadan bazı kod yapmaya çalışıyorum. Yani sadece böyle bir kod var istiyorum:

PropertyPlaceholderConfigurer props = new PropertyPlaceholderConfigurer();
props.load("classpath:/my.properties");
props.get("path");

İlkbaharda özellikler dosyasına erişmenin tam bir örneği aşağıdaki bağlantıdadır: bharatonjava.wordpress.com/2012/08/24/…

Yanıtlar:


171

PropertiesLoaderUtils hakkında ne dersiniz ?

Resource resource = new ClassPathResource("/my.properties");
Properties props = PropertiesLoaderUtils.loadProperties(resource);

5
İşte bir soru, bu benimkinden nasıl farklı ve iki oy daha var VE ikinci gönderdi ...
Zoidberg

3
Beni dövüyor, oy alamadım :) PropertyPlaceholderConfigurerGörev için aşırıya kaçmasına rağmen bir kullanmazdım .
skaffman

5
Mümkün olduğu kadar yakınlaşmaya çalışıyordum, yeterince ayrıntı vermediğim için defalarca reddedildim. Her neyse, cevaplarınız oyları hak ediyor, doğru olduğu için, sanırım sadece kıskanıyorum, 2 oy da alamadım LOL.
Zoidberg

1
dosya harici bir dizine yerleştirilirse yola ne vermeliyiz, diyelim ki yapılandırma klasörü?
prnjn

52

Tüm yapmak istediğiniz yer tutucu değerine koddan @Valueerişmekse , ek açıklama vardır:

@Value("${settings.some.property}")
String someValue;

Yer tutuculara erişmek için SPEL'den bu sözdizimini kullanın:

#('${settings.some.property}')

Yapılandırmayı SPEL'in kapalı olduğu görünümlere göstermek için bu hile kullanılabilir:

package com.my.app;

import java.util.Collection;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.stereotype.Component;

@Component
public class PropertyPlaceholderExposer implements Map<String, String>, BeanFactoryAware {  
    ConfigurableBeanFactory beanFactory; 

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        this.beanFactory = (ConfigurableBeanFactory) beanFactory;
    }

    protected String resolveProperty(String name) {
        String rv = beanFactory.resolveEmbeddedValue("${" + name + "}");

        return rv;
    }

    @Override
    public String get(Object key) {
        return resolveProperty(key.toString());
    }

    @Override
    public boolean containsKey(Object key) {
        try {
            resolveProperty(key.toString());
            return true;
        }
        catch(Exception e) {
            return false;
        }
    }

    @Override public boolean isEmpty() { return false; }
    @Override public Set<String> keySet() { throw new UnsupportedOperationException(); }
    @Override public Set<java.util.Map.Entry<String, String>> entrySet() { throw new UnsupportedOperationException(); }
    @Override public Collection<String> values() { throw new UnsupportedOperationException(); }
    @Override public int size() { throw new UnsupportedOperationException(); }
    @Override public boolean containsValue(Object value) { throw new UnsupportedOperationException(); }
    @Override public void clear() { throw new UnsupportedOperationException(); }
    @Override public String put(String key, String value) { throw new UnsupportedOperationException(); }
    @Override public String remove(Object key) { throw new UnsupportedOperationException(); }
    @Override public void putAll(Map<? extends String, ? extends String> t) { throw new UnsupportedOperationException(); }
}

Ardından özellikleri bir görünüme maruz bırakmak için açıklayıcıyı kullanın:

<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver" id="tilesViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/>
    <property name="attributesMap">
        <map>
            <entry key="config">
                <bean class="com.my.app.PropertyPlaceholderExposer" />
            </entry>
        </map>
    </property>
</bean>

Sonra görünümde, böyle maruz kalan özellikleri kullanın:

${config['settings.some.property']}

Bu çözümün, context: property-placeholder etiketi tarafından enjekte edilen standart yer tutucu uygulamasına güvenebileceğiniz avantajı vardır.

Son bir not olarak, gerçekten tüm yer tutucu özelliklerini ve değerlerini yakalamak için a'ya ihtiyacınız varsa, yer tutucuların özellik değerlerinin içinde beklendiği gibi çalıştığından emin olmak için bunları StringValueResolver aracılığıyla yönlendirmeniz gerekir. Aşağıdaki kod bunu yapar.

package com.my.app;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.util.StringValueResolver;

public class AppConfig extends PropertyPlaceholderConfigurer implements Map<String, String> {

    Map<String, String> props = new HashMap<String, String>();

    @Override
    protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props)
            throws BeansException {

        this.props.clear();
        for (Entry<Object, Object> e: props.entrySet())
            this.props.put(e.getKey().toString(), e.getValue().toString());

        super.processProperties(beanFactory, props);
    }

    @Override
    protected void doProcessProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
            StringValueResolver valueResolver) {

        super.doProcessProperties(beanFactoryToProcess, valueResolver);

        for(Entry<String, String> e: props.entrySet())
            e.setValue(valueResolver.resolveStringValue(e.getValue()));
    }

    // Implement map interface to access stored properties
    @Override public Set<String> keySet() { return props.keySet(); }
    @Override public Set<java.util.Map.Entry<String, String>> entrySet() { return props.entrySet(); }
    @Override public Collection<String> values() { return props.values(); }
    @Override public int size() { return props.size(); }
    @Override public boolean isEmpty() { return props.isEmpty(); }
    @Override public boolean containsValue(Object value) { return props.containsValue(value); }
    @Override public boolean containsKey(Object key) { return props.containsKey(key); }
    @Override public String get(Object key) { return props.get(key); }
    @Override public void clear() { throw new UnsupportedOperationException(); }
    @Override public String put(String key, String value) { throw new UnsupportedOperationException(); }
    @Override public String remove(Object key) { throw new UnsupportedOperationException(); }
    @Override public void putAll(Map<? extends String, ? extends String> t) { throw new UnsupportedOperationException(); }
}

Bu tam cevap için teşekkürler! bunu son alanlarla yapmanın bir yolu var mı?
Ward

2
@ Son bir alana enjekte edemezsiniz. Ancak, bir yapıcı bağımsız değişkenine enjekte edebilir ve yapıcı içinde bir son alan değeri ayarlayabilirsiniz. Bkz. Stackoverflow.com/questions/2306078/… ve stackoverflow.com/questions/4203302/…
anttix

50

KREDİ : Özellikler dosyasını yeniden okumadan ilkbahardaki özelliklere programlı erişim

Ben bahar zaten yüklü aynı özellikleri yeniden yüklemeden baharda programsal olarak özelliklere erişim güzel bir uygulama buldum. [Ayrıca, kaynaktaki özellik dosyasının konumunu kodlamak gerekli değildir]

Bu değişikliklerle, kod daha temiz ve daha bakımlı görünür.

Konsept oldukça basit. Yay varsayılan özelliği yer tutucusunu (PropertyPlaceholderConfigurer) genişletmeniz ve yerel değişkene yüklediği özellikleri yakalamanız yeterlidir

public class SpringPropertiesUtil extends PropertyPlaceholderConfigurer {

    private static Map<String, String> propertiesMap;
    // Default as in PropertyPlaceholderConfigurer
    private int springSystemPropertiesMode = SYSTEM_PROPERTIES_MODE_FALLBACK;

    @Override
    public void setSystemPropertiesMode(int systemPropertiesMode) {
        super.setSystemPropertiesMode(systemPropertiesMode);
        springSystemPropertiesMode = systemPropertiesMode;
    }

    @Override
    protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props) throws BeansException {
        super.processProperties(beanFactory, props);

        propertiesMap = new HashMap<String, String>();
        for (Object key : props.keySet()) {
            String keyStr = key.toString();
            String valueStr = resolvePlaceholder(keyStr, props, springSystemPropertiesMode);
            propertiesMap.put(keyStr, valueStr);
        }
    }

    public static String getProperty(String name) {
        return propertiesMap.get(name).toString();
    }

}

Kullanım Örneği

SpringPropertiesUtil.getProperty("myProperty")

Yay konfigürasyonu değişiklikleri

<bean id="placeholderConfigMM" class="SpringPropertiesUtil">
    <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
    <property name="locations">
    <list>
        <value>classpath:myproperties.properties</value>
    </list>
    </property>
</bean>

Umarım sahip olduğunuz sorunları çözmeye yardımcı olur


8
Bu tam bir uygulama değildir ve düzgün çalışmaz. PropertyPlaceholderConfigurer, iç içe yer tutucular dahil TÜM yer tutucu özelliklerini değiştirmek için bir PropertyPlaceholderHelper kullanır. Kalinga'nın uygulamasında myFile = $ {myFolder} /myFile.txt gibi bir şeye sahipseniz, haritadan "myFile" anahtarını kullanarak alacağınız değişmez özellik değeri $ {myFolder} /myFile.txt olacaktır.

1
Bu doğru çözüm. Brian'ın endişesini gidermek için. $ {MyFolder} bir sistem özelliği olmalı ve özellikler dosyasında olmamalıdır. Bu, tomcat system özelliğine veya eclipse içinde çalıştırılan özelliğe ayarlanarak çözülebilir. Bir yapı özelliğiniz bile olabilir. Bu çözüm, biraz çözüm olduğunu ve aynı zamanda bu cevabın, yay ve java özelliklerini ayrı ayrı yerine tek bir yerde yüklemek için standart uygulama hattı boyunca çok daha fazla olduğunu varsaymaktadır. Başka bir seçenek, dosyaya myFile ile genel özellikler dosyasını yüklemek ve geri kalanını almak için bunu kullanmaktır.
Rob

1
Bu geçici çözümü 'Bahar' 3.1 'yeni' PropertySourcesPlaceholderConfigurer uygulamak için çalıştı ama yöntem processProperties (ConfigurableListableBeanFactory beanFactory, Özellikler sahne) artık kullanımdan kaldırıldı ve bu nedenle şimdi 'sahne' argümanı erişim olmadığını buldum. PropertySourcesPlaceholderConfigurer'ın kaynaklarına bakmak, özellikleri göstermenin temiz bir yolunu bulamıyor. Bunu yapmak için herhangi bir fikrin var mı? Teşekkürler!
Jorge Palacio

48

Bunu yaptım ve işe yaradı.

Properties props = PropertiesLoaderUtils.loadAllProperties("my.properties");
PropertyPlaceholderConfigurer props2 = new PropertyPlaceholderConfigurer();
props2.setProperties(props);

Bu işe yaramalı.


25

Ayrıca yay araçlarını kullanabilir veya PropertiesFactoryBean aracılığıyla özellikleri yükleyebilirsiniz.

<util:properties id="myProps" location="classpath:com/foo/myprops.properties"/>

veya:

<bean id="myProps" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
  <property name="location" value="classpath:com/foo/myprops.properties"/>
</bean>

Daha sonra bunları uygulamanızda şunlarla alabilirsiniz:

@Resource(name = "myProps")
private Properties myProps;

ve ek olarak yapılandırmanızda şu özellikleri kullanın:

<context:property-placeholder properties-ref="myProps"/>

Bu, dokümanlar da içindedir: http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#xsd-config-body-schemas-util-properties


10

Aşağıdaki gibi bir sınıf oluşturun

    package com.tmghealth.common.util;

    import java.util.Properties;

    import org.springframework.beans.BeansException;

    import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

    import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;

    import org.springframework.context.annotation.Configuration;

    import org.springframework.context.annotation.PropertySource;

    import org.springframework.stereotype.Component;


    @Component
    @Configuration
    @PropertySource(value = { "classpath:/spring/server-urls.properties" })
    public class PropertiesReader extends PropertyPlaceholderConfigurer {

        @Override
        protected void processProperties(
                ConfigurableListableBeanFactory beanFactory, Properties props)
                throws BeansException {
            super.processProperties(beanFactory, props);

        }

    }

Sonra bir mülk kullanımına erişmek istediğiniz her yerde

    @Autowired
        private Environment environment;
    and getters and setters then access using 

    environment.getProperty(envName
                    + ".letter.fdi.letterdetails.restServiceUrl");

- erişimci sınıfına alıcılar ve ayarlayıcılar yazma

    public Environment getEnvironment() {
            return environment;
        }`enter code here`

        public void setEnvironment(Environment environment) {
            this.environment = environment;
        }

1
Şimdiye kadar en iyi cevap, sadece Çevre otomatik bağlanmalıdır.
sbochins

4

Bildiğiniz gibi Spring'in yeni sürümleri PropertyPlaceholderConfigurer'ı kullanmaz ve şimdi PropertySourcesPlaceholderConfigurer adlı başka bir kabus yapısı kullanır. Koddan çözümlenmiş mülkler almaya çalışıyorsanız ve Bahar ekibinin bize bunu uzun zaman önce yapmanın bir yolunu vermesini istiyorsanız, bu gönderiyi oylayın! ... Çünkü yeni şekilde böyle yapıyorsunuz:

Alt sınıf PropertySourcesPlaceholderConfigurer:

public class SpringPropertyExposer extends PropertySourcesPlaceholderConfigurer {

    private ConfigurableListableBeanFactory factory;

    /**
     * Save off the bean factory so we can use it later to resolve properties
     */
    @Override
    protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
            final ConfigurablePropertyResolver propertyResolver) throws BeansException {
        super.processProperties(beanFactoryToProcess, propertyResolver);

        if (beanFactoryToProcess.hasEmbeddedValueResolver()) {
            logger.debug("Value resolver exists.");
            factory = beanFactoryToProcess;
        }
        else {
            logger.error("No existing embedded value resolver.");
        }
    }

    public String getProperty(String name) {
        Object propertyValue = factory.resolveEmbeddedValue(this.placeholderPrefix + name + this.placeholderSuffix);
        return propertyValue.toString();
    }
}

Kullanmak için, alt sınıfınızı @Yapılandırmanızda kullandığınızdan emin olun ve daha sonra kullanmak üzere referansı kaydedin.

@Configuration
@ComponentScan
public class PropertiesConfig {

    public static SpringPropertyExposer commonEnvConfig;

    @Bean(name="commonConfig")
    public static PropertySourcesPlaceholderConfigurer commonConfig() throws IOException {
        commonEnvConfig = new SpringPropertyExposer(); //This is a subclass of the return type.
        PropertiesFactoryBean commonConfig = new PropertiesFactoryBean();
        commonConfig.setLocation(new ClassPathResource("META-INF/spring/config.properties"));
        try {
            commonConfig.afterPropertiesSet();
        }
        catch (IOException e) {
            e.printStackTrace();
            throw e;
        }
        commonEnvConfig.setProperties(commonConfig.getObject());
        return commonEnvConfig;
    }
}

Kullanımı:

Object value = PropertiesConfig.commonEnvConfig.getProperty("key.subkey");

2

İşte başka bir örnek.

XmlBeanFactory factory = new XmlBeanFactory(new FileSystemResource("beans.xml"));
PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer();
cfg.setLocation(new FileSystemResource("jdbc.properties"));
cfg.postProcessBeanFactory(factory);

2

Bu bana yardım et:

ApplicationContextUtils.getApplicationContext().getEnvironment()

ApplicationContextUtils paketi nedir
Luke

2

Bu, yuvalanmış özellikleri çözecektir.

public class Environment extends PropertyPlaceholderConfigurer {

/**
 * Map that hold all the properties.
 */
private Map<String, String> propertiesMap; 

/**
 * Iterate through all the Property keys and build a Map, resolve all the nested values before building the map.
 */
@Override
protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props) throws BeansException {
    super.processProperties(beanFactory, props);

    propertiesMap = new HashMap<String, String>();
    for (Object key : props.keySet()) {
        String keyStr = key.toString();
        String valueStr = beanFactory.resolveEmbeddedValue(placeholderPrefix + keyStr.trim() + DEFAULT_PLACEHOLDER_SUFFIX);
        propertiesMap.put(keyStr, valueStr);
    }
} 

/**
 * This method gets the String value for a given String key for the property files.
 * 
 * @param name - Key for which the value needs to be retrieved.
 * @return Value
 */
public String getProperty(String name) {
    return propertiesMap.get(name).toString();
}

2

Özelliklerinizi Environmentsınıf aracılığıyla alabilirsiniz . Belgelerin ifade ettiği gibi:

Özellikler hemen hemen tüm uygulamalarda önemli bir rol oynar ve çeşitli kaynaklardan kaynaklanabilir: özellikler dosyaları, JVM sistem özellikleri, sistem ortam değişkenleri, JNDI, sunucu uygulaması bağlam parametreleri, geçici Özellikler nesneleri, Haritalar vb. Ortam nesnesinin özelliklere ilişkin rolü, kullanıcıya özellik kaynaklarını yapılandırmak ve bunlardan özellikleri çözmek için uygun bir hizmet arabirimi sağlamaktır.

envDeğişken olarak Ortama sahip olmak için şunu aramanız yeterlidir:

env.resolvePlaceholders("${your-property:default-value}")

'Ham' mülklerinizi şu yollarla alabilirsiniz:

env.getProperty("your-property")

Baharın kaydettiği tüm özellikler kaynağını arayacaktır.

Ortamı aşağıdaki yollarla elde edebilirsiniz:

  • uygulayarak ApplicationContext'i enjekte edin ApplicationContextAwareve ardındangetEnvironment() bağlamı
  • uygulamak EnvironmentAware.

Fasulye yapımı için gerekli olabileceğinden, özellikler uygulamanın başlatılmasının erken aşamasında çözüldüğü için bir sınıfın uygulanmasıyla elde edilir.

Dokümantasyon hakkında daha fazla bilgi: bahar Çevre dokümantasyonu


1

Bu yazı ayrıca mülklere nasıl erişileceğini de açıklamaktadır: http://maciej-miklas.blogspot.de/2013/07/spring-31-programmatic-access-to.html

Yay özelliği yer tutucusu tarafından yüklenen özelliklere bu bahar çekirdeği üzerinden erişebilirsiniz:

@Named
public class PropertiesAccessor {

    private final AbstractBeanFactory beanFactory;

    private final Map<String,String> cache = new ConcurrentHashMap<>();

    @Inject
    protected PropertiesAccessor(AbstractBeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

    public  String getProperty(String key) {
        if(cache.containsKey(key)){
            return cache.get(key);
        }

        String foundProp = null;
        try {
            foundProp = beanFactory.resolveEmbeddedValue("${" + key.trim() + "}");
            cache.put(key,foundProp);
        } catch (IllegalArgumentException ex) {
           // ok - property was not found
        }

        return foundProp;
    }
}

0
create .properties file in classpath of your project and add path configuration in xml`<context:property-placeholder location="classpath*:/*.properties" />`

bundan sonra dosyanızı her yerde doğrudan kullanabilirsiniz.


0

Dosyayı uygulamanızın sınıf yolundan yüklemek için lütfen bahar yapılandırma dosyanızda aşağıdaki kodu kullanın

 <context:property-placeholder
    ignore-unresolvable="true" ignore-resource-not-found="false" location="classpath:property-file-name" />

0

Bu işe en iyi şekilde:

package your.package;

import java.io.IOException;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PropertiesLoaderUtils;

public class ApplicationProperties {

    private Properties properties;

    public ApplicationProperties() {
        // application.properties located at src/main/resource
        Resource resource = new ClassPathResource("/application.properties");
        try {
            this.properties = PropertiesLoaderUtils.loadProperties(resource);
        } catch (IOException ex) {
            Logger.getLogger(ApplicationProperties.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public String getProperty(String propertyName) {
        return this.properties.getProperty(propertyName);
    }
}

Sınıfı ve çağrı yöntemini obj.getProperty ("my.property.name");
Daniel Almeida
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.