11 Stimmen

Laden von Eigenschaften mit Spring (über Systemeigenschaften)

Mein Problem ist folgendes:

Ich habe server.properties für unterschiedliche Umgebungen. Der Pfad zu diesen Eigenschaften wird über eine Systemeigenschaft namens propertyPath . Wie kann ich meine Mitarbeiter anweisen applicationContext.xml zum Laden der Eigenschaften mit dem angegebenen propertyPath Systemeigenschaft ohne hässliche MethodInvokingBean die aufruft System.getProperty('');

Meine applicationContext.xml

<bean id="systemPropertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
        <property name="placeholderPrefix" value="sys{"/>
        <property name="properties">
            <props>
                <prop key="propertyPath">/default/path/to/server.properties</prop>
            </props>
        </property>
    </bean>

    <bean id="propertyResource" class="org.springframework.core.io.FileSystemResource" dependency-check="all" depends-on="systemPropertyConfigurer">
        <constructor-arg value="sys{propertyPath}"/>
    </bean>

    <bean id="serviceProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
        <property name="location" ref="propertyResource"/>
    </bean>

    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" ref="propertyResource"/>
        <property name="placeholderPrefix" value="prop{"/>

        <property name="ignoreUnresolvablePlaceholders" value="true"/>
        <property name="ignoreResourceNotFound" value="false"/>
    </bean>

    <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
         <property name="jndiName" value="prop{datasource.name}"/>
    </bean>

Bei dieser Konfiguration beschwert sich die PropertyResource auch immer über

java.io.FileNotFoundException: sys{propertyPath} (The system cannot find the file specified)

Irgendwelche Vorschläge? ;-) Danke Gabe

EDIT:

Jetzt habe ich den Ladeprozess der Beans debuggt und es scheint, dass die setLocation Methode der propertyConfigurer aufgerufen wird, bevor die systemPropertyConfigurer erstellt wird, so dass die propertyResource mit "sys{propertyPath}" initialisiert wird. Ich habe herumgespielt mit depends-on aber kein Glück.

0 Stimmen

Wie genau haben Sie mit depends-on gespielt?

0 Stimmen

PropertyResource depends-on="systemPropertyConfigurer"' scheint keine Auswirkung zu haben. propertyResource wird trotzdem zuerst initialisiert, vielleicht weil es mit dem Konstruktor-Arg initialisiert wird

6voto

n3utrino Punkte 2353

Okay, ich habe es gelöst. Das Problem ist, dass meine beiden PropertyPlaceholder BeanFactoryPostProcessor sind, die verarbeitet werden, nachdem der Kontext geladen wird, aber die Eigenschaften werden nach gesetzt. Also ist es unmöglich, einen PropertyPlaceholder mit einem anderen zu bestücken .

Hier ist meine Lösung im Code ;-)

package property.util;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;

import java.io.IOException;
import java.util.Properties;

/**
 * ConfigurablePropertyPlaceholder takes instructions which SystemProperty
 * contains the path to the propertyfile to load.
 *
 * @author Gabe Kaelin
 * 
 */
public class ConfigurablePropertyPlaceholder extends PropertyPlaceholderConfigurer {

    private String propertyLocationSystemProperty;
    private String defaultPropertyFileName;

    public String getPropertyLocationSystemProperty() {
        return propertyLocationSystemProperty;
    }

    public void setPropertyLocationSystemProperty(String propertyLocationSystemProperty) {
        this.propertyLocationSystemProperty = propertyLocationSystemProperty;
    }

    public String getDefaultPropertyFileName() {
        return defaultPropertyFileName;
    }

    public void setDefaultPropertyFileName(String defaultPropertyFileName) {
        this.defaultPropertyFileName = defaultPropertyFileName;
    }

    /**
     * Overridden to fill the location with the path from the {@link #propertyLocationSystemProperty}
     *
     * @param props propeties instance to fill
     * @throws IOException
     */

    @Override
    protected void loadProperties(Properties props) throws IOException {
        Resource location = null;
        if(StringUtils.isNotEmpty(propertyLocationSystemProperty)){

            String propertyFilePath = System.getProperties().getProperty(propertyLocationSystemProperty);
            StringBuilder pathBuilder = new StringBuilder(propertyFilePath);

            if(StringUtils.isNotEmpty(defaultPropertyFileName) && !propertyFilePath.endsWith(defaultPropertyFileName)){
                pathBuilder.append("/").append(defaultPropertyFileName);
            }

            location = new FileSystemResource(pathBuilder.toString());
        }

        setLocation(location);
        super.loadProperties(props);
    }
}

Der entsprechende applicationContext.xml-Eintrag

<bean id="propertyConfigurer" class="property.util.ConfigurablePropertyPlaceholder">
  <property name="propertyLocationSystemProperty" value="propertyPath" />
  <property name="defaultPropertyFileName" value="server.properties" />
  <property name="ignoreResourceNotFound" value="false"/>
</bean>

Der Java-Prozess kann gestartet werden mit

java -DpropertyPath=/path/to/properties

und lädt die Eigenschaften, die in der Datei applicationContext.xml verfügbar sind

2voto

Die angegebene Lösung zur Erweiterung von PropertyPlaceholderConfigurer scheint in Ordnung zu sein, aber es sollte auch funktionieren, indem man sich auf die Standardimplementierung von org.springframework.beans.factory.config.PropertiesFactoryBean verlässt, ohne zusätzlichen Code zu schreiben.

Verwenden Sie einfach die Variablenreferenz, die von Spring aufgelöst wird.

z.B..

Konfigurieren Sie die Feder wie folgt:

<bean id="configProp"
      class="org.springframework.beans.factory.config.PropertiesFactoryBean">
    <property name="locations">
        <list>
            <value>file:${propertyPath}</value>
        </list>
    </property>
</bean>

Sobald Sie Java mit der env-Variable (propertyPath) aufrufen, löst Spring diese auf, lädt die Property-Datei und injiziert sie in den Anwendungskontext

java -DpropertyPath=/path/to/properties

0 Stimmen

Sie können sogar einen Standardwert konfigurieren, wenn propertyPath ist nicht festgelegt worden: ${propertyPath:defaultValue}

1voto

Bozho Punkte 570413

Sie haben zwei Möglichkeiten:

  • verwenden. sys: als Präfix (und damit sys:propertyPath )

  • setzen die placeholderSuffix Eigenschaft des Platzhalterkonfigurators auf } , so dass Sie auf die Eigenschaften mit sys{prop} . Wenn Sie diese Eigenschaft weglassen, müssen Sie sys{prop

1 Stimmen

Vielen Dank für die Tipps. Aber ich kann es nicht zum Laufen bringen. Vielleicht habe ich etwas übersehen. Es wirft immer ein FileNotFoundEx mit dem Eigenschaftsnamen als Datei. die Standard-PlatzhalterSuffix ist } so gibt es keine Notwendigkeit, es zu spezifizieren ich denke, es gibt ein Problem mit der Reihenfolge des Ladens der Bohnen

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X