使用Spring注释读取文件属性

时间:2015-03-03 09:55:06

标签: java spring properties annotations

我正在尝试学习如何使用spring读取属性文件。在互联网搜索后,我发现我可以使用@value@PropertySource注释来实现这一目标。我创建了一个具有以下结构和类代码的项目:

项目结构:

enter image description here

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

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());
  }
}

我正在读取的属性文件名为config.properties,它包含以下行:

mongodb.url=1.2.3.4
mongodb.db=dataBase

我测试了这个小项目,我得到了一个包含以下异常的堆栈跟踪:

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

是Spring调用bean的问题吗?或者可能是属性文件路径或其他问题?

2 个答案:

答案 0 :(得分:21)

我可以在代码中看到几个问题。

1)您的值的占位符应采用${mogodb.url}形式,而不是#{mongodb.url}。 &#34;#&#34;具有不同的含义(见Spring Expressions)。

2)您将需要一个PropertySourcesPlaceholderConfigurer bean来注入值

3)迟早你会有一些豆子漂浮在周围,我会用@ComponentScan让上下文知道这些,而你不必一个一个地提到它们

4)如果使用ComponentScan获取bean,则必须提供AppConfigMongoDB bean一次

在完成所有这些后,我最终得到了这些类:

<强> 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;
  }
}

答案 1 :(得分:0)

@Ian Sparkes给出了很好的答复。在此处添加一些输入。配置PropertySourcesPlaceholderConfigurer不是必需的。我可以从属性文件中获取该值,并将其设置为我的主Configuration类的文件变量(不带该值)。

还有另一种方法来获取属性文件中键的值。使用org.springframework.core.env.Environment类。此类自动将所有键值对加载到类路径中的属性文件中。

示例:

@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;
	}
}