/ / Comment passer d'un fichier de configuration statique codé en dur à un fichier .properties? - java, refactoring

Comment passer d'un fichier de configuration statique codé en dur à un fichier .properties? - java, refactoring

J'ai un code qui utilise une classe contenant un grand nombre de constantes codées en dur. Voici à quoi ça ressemble:

class Constants{
public static final String name1 = "value1";
public static final String name2 = "value2";
public static final Integer value3 = 3;
... and so on
}

Ces constantes sont utilisées partout dans le code comme Constants.name1.

Ce que je dois faire maintenant, c’est de permettre de spécifier des valeurs pour ces constantes dans un fichier de configuration, probablement un fichier. *.properties fichier.

Ma question est la suivante: quelle est la meilleure façon de le faire, de réécrire le moins de code possible?

J'ai pensé à utiliser une seule classe de configurationqui lit les propriétés du fichier lorsqu’il est instancié, mais je devrai ensuite remplacer tous les appels statiques de valeurs aux appels d’une instance de cette classe et modifier les méthodes existantes pour leur transmettre cette instance de configuration. Y a-t-il un meilleur moyen?

Réponses:

4 pour la réponse № 1

Voici un morceau de code que j'ai utilisé dans le passé - qui peut être adapté à votre exemple:

public enum Configuration {

PROPERTY1("property1.name", "default_value_1"),
PROPERTY2("property2.name", "default_value_2");

private final String key;
private String defaultValue;

Configuration(String key) {
this(key, NA);
}

Configuration(String key, String defaultValue) {
this.key = key;
this.defaultValue = defaultValue;
}
private final static Logger logger = LoggerFactory.getLogger(Configuration.class);
private final static String NA = "n.a.";
private final static String CONFIG_FILE = "properties/config.properties";
private final static String NOT_A_VALID_KEY = "Not a valid property key";
private final static Map<Configuration, String> configuration = new EnumMap<>(Configuration.class);

static {
readConfigurationFrom(CONFIG_FILE);
}

private static void readConfigurationFrom(String fileName) {
logger.info("Reading resource: {}", fileName);
try (InputStream resource = Configuration.class.getClassLoader().getResourceAsStream(fileName);) {
Properties properties = new Properties();
properties.load(resource); //throws a NPE if resource not founds
for (String key : properties.stringPropertyNames()) {
configuration.put(getConfigurationKey(key), properties.getProperty(key));
}
} catch (IllegalArgumentException | IOException | NullPointerException e) {
logger.error("Error while reading the properties file {}", fileName, e);
populateDefaultValues();
}
}

private static Configuration getConfigurationKey(String key) {
for (Configuration c : values()) {
if (c.key.equals(key)) {
return c;
}
}
throw new IllegalArgumentException(NOT_A_VALID_KEY + ": " + key);
}

private static void populateDefaultValues() {
for (Configuration c : values()) {
configuration.put(c, c.defaultValue);
}
}

/**
* @return the property corresponding to the key or null if not found
*/
public String get() {
return configuration.get(this);
}
}

3 pour la réponse № 2

Chargez les propriétés du fichier en utilisant Properties.load(...) et assigner les constantes à partir de ces propriétés.

class Constants{
public static final String name1;
public static final String name2;
public static final Integer value3;

static{
Properties p = new Properties();
try ( FileInputStream stream = new FileInputStream( new File("path/to/file.properties") )) {
p.load( stream );
}catch( Exception e ){
//handle exceptions
}

name1 = p.getProperty( "name1" );
name2 = p.getProperty( "name2" );
value3 = Integer.valueOf( p.getProperty( "value3" ) );
}

Notez que ceci est juste une solution rapide et sale et fait beaucoup d'hypothèses. Il serait préférable de gérer les exceptions individuelles et vous devez également gérer les NumberFormatException qui pourrait être jeté par Integer.valueOf(...) si la configuration est vide ou pas un nombre.

Autre remarque: vous pouvez également essayer d’utiliser une configuration non statique ou au moins non définitive afin de pouvoir modifier les propriétés au moment de l’exécution.

modifier: J'ai ajouté autoclose pour le flux, mais notez qu'avant Java 7, vous deviez le gérer vous-même.


2 pour la réponse № 3

En un tour de main, vous pouvez lire le fichier de propriétés dans le static initialiseur de la classe, alors vous n’avez pas à changer immédiatement la nature statique des champs de la classe, mais je vous suggère de le faire quand même.

Créez une nouvelle classe contenant toutes vos anciennes valeurs constantes. A partir de maintenant, insérez cet objet de configuration dans votre nouveau code.

class NewConstants {
public final String name1;
public final String name2;
public final Integer value3;
... and so on

public NewConstants ( Properties props )
{
name1 = props.getProperty( "name1" );
...
}
}

Maintenant, refactor ton vieux Constants classe

class Constants (
public static final String name1;
public static final String name2;
public static final Integer value3;

static {
Properties props = new Poperties( );
props.load( ... );

NewConstants newConstants = new NewConstants( props );

name1 = newConstants.getName1( );
name2 = newConstants.getName2( );

...
}
}