web-dev-qa-db-fra.com

Lire les propriétés du fichier à l'aide des annotations Spring

J'essaie d'apprendre à lire le fichier de propriétés à l'aide de spring. Après une recherche sur Internet, j'ai constaté que je pouvais utiliser les annotations @value et @PropertySource pour y parvenir. J'ai créé un projet qui a la structure et les codes de classes suivants:

Structure du projet:

enter image description here

Implémentation AppConfigMongoDB.Java:

package com.mongodb.properties;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;


@PropertySource("classpath:config/config.properties")
public class AppConfigMongoDB {

@Value("#{mongodb.url}")
private String mongodbUrl;


@Value("#{mongodb.db}")
private String defaultDb;

public String getMongoDb()
{
    return defaultDb;
}

public String getMongoDbUrl()
{
    return mongodbUrl;
}
}

Implémentation SpringConfiguration.Java:

 package com.mongodb.properties;

 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;

 @Configuration
 public class SpringConfiguration {
 @Bean
 public AppConfigMongoDB getAppConfigMongoDB(){
        return new AppConfigMongoDB();
  }
 }

Main.Java

package com.mongodb.properties;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {

public static void main(String[] args) {
    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfiguration.class);
    AppConfigMongoDB mongo = applicationContext.getBean(AppConfigMongoDB.class);
    System.out.println("db= "+mongo.getMongoDb());
    System.out.println("URL= "+mongo.getMongoDbUrl());
  }
}

Le fichier de propriétés que je lis s'appelle config.properties. Il contient les lignes suivantes:

mongodb.url=1.2.3.4
mongodb.db=dataBase

J'ai testé ce petit projet et une trace de pile contenant l'exception suivante:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'getAppConfigMongoDB': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private Java.lang.String com.mongodb.properties.AppConfigMongoDB.mongodbUrl; nested exception is org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 0): Property or field 'mongodb' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public?
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.Java:334)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.Java:1202)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.Java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.Java:476)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.Java:303)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.Java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.Java:299)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.Java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.Java:755)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.Java:757)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.Java:480)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.Java:84)
at com.mongodb.properties.Main.main(Main.Java:9)

 Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 0): Property or field 'mongodb' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public?
at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.Java:226)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.Java:93)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.Java:81)
at org.springframework.expression.spel.ast.CompoundExpression.getValueRef(CompoundExpression.Java:51)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.Java:87)
at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.Java:120)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.Java:242)
at org.springframework.context.expression.StandardBeanExpressionResolver.evaluate(StandardBeanExpressionResolver.Java:161)
... 18 more

Est-ce un problème de printemps appelant des haricots? Ou peut-être est-ce un problème de chemin du fichier de propriétés ou autre chose?

10
Kallel Omar

Je peux voir plusieurs problèmes dans le code.

1) Les espaces réservés aux valeurs doivent être au format ${mogodb.url} et non pas au #{mongodb.url} Le "#" a un sens différent (voir expressions de printemps ). 

2) Vous allez avoir besoin d'un haricot PropertySourcesPlaceholderConfigurer pour faire l'injection des valeurs

3) Tôt ou tard, vous allez avoir un certain nombre de Beans flottants, et j'utiliserais @ComponentScan pour permettre au contexte de les connaître sans que vous ayez à les mentionner un par un

4) Si vous utilisez ComponentScan pour obtenir les haricots, vous devrez fournir une fois AppConfigMongoDB bean

Je me retrouve avec ces cours après avoir fait tout ça:

Main.Java

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {

public static void main(String[] args) {
    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfiguration.class);
    AppConfigMongoDB mongo = applicationContext.getBean(AppConfigMongoDB.class);
    System.out.println("db= "+mongo.getMongoDb());
    System.out.println("URL= "+mongo.getMongoDbUrl());
  }
}

SpringConfiguration.Java

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;

@Configuration
@ComponentScan
public class SpringConfiguration {

  @Bean
  public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
    return new PropertySourcesPlaceholderConfigurer();
  }
}

AppConfigMongoDB.Java

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@Configuration
@PropertySource("classpath:config/config.properties")
public class AppConfigMongoDB {

  @Value("${mongodb.url}")
  private String mongodbUrl;

  @Value("${mongodb.db}")
  private String defaultDb;

  public String getMongoDb() {
    return defaultDb;
  }

  public String getMongoDbUrl() {
    return mongodbUrl;
  }
}
21
ISparkes

Belle réponse donnée par @Ian Sparkes. Ajout de certaines de mes entrées ici. La configuration de PropertySourcesPlaceholderConfigurer n'est pas obligatoire. Je peux obtenir la valeur de mon fichier de propriétés et la définir sur la variable classée de ma classe de configuration principale sans celle-ci. 

Il existe également un autre moyen d’obtenir les valeurs de vos clés dans le fichier de propriétés. Utilisez la classe org.springframework.core.env.Environment. Cette classe charge automatiquement toutes les paires clé-valeur dans le fichier de propriétés situé dans le chemin de la classe. 

Exemple : 

@Configuration
@ComponentScan(basePackages="com.easy.buy")
@PropertySource({"classpath:config.properties","classpath:props/db-${env}-config.properties", 
	"classpath:props/app-${env}-config.properties"})
public class CatalogServiceConfiguration {
	Logger logger = LoggerFactory.getLogger(CatalogServiceConfiguration.class);
	
	//This object loads & holds all the properties in it as key-pair values
	@Autowired
	private Environment env;
	
	/**
	 * Instantiate the DataSource bean & initialize it with db connection properties
	 * @return
	 */
	@Bean(name="basicDataSource")
	public BasicDataSource basicDataSource() {
		String dbUrl = env.getProperty("db.url");
		String dbUser = env.getProperty("db.user");
		String dbPwd = env.getProperty("db.pwd");
		String driver = env.getProperty("db.driver");
		
		logger.info("Initializing CatalogServiceConfiguration");
		logger.info("dbUrl=" + dbUrl);
		
		BasicDataSource ds = new BasicDataSource();
		ds.setDriverClassName(driver);
		ds.setUrl(dbUrl);
		ds.setUsername(dbUser);
		ds.setPassword(dbPwd);
		
		return ds;
	}
}

0
Ayaskant