spring註解注入properties配置文件

spring自3.1版本後,增長了新的註解@PropertySource,用於註解注入配置文件的屬性

 

之前,咱們配置讀取配置文件,通常都是在XML文件裏面配置,其實,這不是很利於維護,畢竟要去XML裏面找配置,還須要把對象註冊爲bean,讓xml顯得過於臃腫,以下就是之前讀取xml讀取properties文件的配置,相信很多同窗都知道.java

 

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

 

可是如今咱們有註解的形式來配置了,讓咱們先來看一段源碼,是關於註解@PropertySource註解的mysql

 

從上面的註釋,能夠發現,@propertySource註解是自spring 3.1版本開始有的,是一個配置註解,用於注入properties文件的屬性的.下面,開始上測試代碼吧.spring

 

--------------------------------我是分割線--------------------------------------sql

 

先看配置文件裏面的內容:app

userBean.name=hexiaowu
userBean.sex=男
userBean.isflag=true

而後看測試註解注入的類:ide

 

@Component
@PropertySource(value = "classpath:properties/config_userbean.properties",ignoreResourceNotFound = true)
public class DemoAnnotation {

   //注入peoperties文件裏面的屬性
   @Value("${userBean.name}")
   private String propertie_name;


   /**
    *        使用@value註解注入properties中的屬性
    *    1.在類名上面使用  @PropertySource("classpath:*") 註解,*表明屬性文件路徑,能夠指向多個配置文件路徑
    *        若是是多個配置文件,則是 @PropertySource({"classpath:*","classpath:*"....})
    *    2.ignoreResourceNotFound=true 表示若是配置文件不存在,則忽略報錯
    *    3.在字段上直接使用@value註解
    *    4.註解內使用${userBean.name}  userBean.name 表明屬性文件裏面的key
    *    5.須要新增 PropertySourcesPlaceholderConfigurer   的bean
    *    6.在  PropertySourcesPlaceholderConfigurer 增長@bean註解,申明返回的是一個bean,不然會注入不成功
    *
    */

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

   public String getPropertie_name() {
      return propertie_name;
   }

   public void setPropertie_name(String propertie_name) {
      this.propertie_name = propertie_name;
   }

   @Override
   public String toString() {
      return "DemoAnnotation{"  +
            ", propertie_name='" + propertie_name + '\'' +
            '}';

 

有同窗會很納悶了,爲何要返回一個 PropertySourcesPlaceholderConfigurer 的bean呢?讓咱們來看看源碼吧.

PS:由於前面本人對 PropertySourcesPlaceholderConfigurer 理解有誤,致使下面解釋的模棱兩可,由於spring是經過PropertySourcesPlaceholderConfigurer 內locations來查找屬性文件,而後在根據註解將匹配的屬性set進去,而下面的註釋解釋,是表示用註解能夠作一些什麼操做..測試

 

public class PropertySourcesPlaceholderConfigurer extends PlaceholderConfigurerSupport
        implements EnvironmentAware {

    /**
     * {@value} is the name given to the {@link PropertySource} for the set of
     * {@linkplain #mergeProperties() merged properties} supplied to this configurer.
     */
    public static final String LOCAL_PROPERTIES_PROPERTY_SOURCE_NAME = "localProperties";

    /**
     * {@value} is the name given to the {@link PropertySource} that wraps the
     * {@linkplain #setEnvironment environment} supplied to this configurer.
     */
    public static final String ENVIRONMENT_PROPERTIES_PROPERTY_SOURCE_NAME = "environmentProperties";


    private MutablePropertySources propertySources;

    private PropertySources appliedPropertySources;

    private Environment environment;

    下面代碼省略.....

上面源碼,並沒能看出爲何必定要返回這個bean,那麼我看就看看他的父類 PlaceholderConfigurerSupport 吧.如下是父類的源碼this

/**
 * Abstract base class for property resource configurers that resolve placeholders
 * in bean definition property values. Implementations <em>pull</em> values from a
 * properties file or other {@linkplain org.springframework.core.env.PropertySource
 * property source} into bean definitions.
 *
 * <p>The default placeholder syntax follows the Ant / Log4J / JSP EL style:
 *
 *<pre class="code">${...}</pre>
 *
 * Example XML bean definition:
 *
 *<pre class="code">{@code
 *<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"/>
 *    <property name="driverClassName" value="}${driver}{@code "/>
 *    <property name="url" value="jdbc:}${dbname}{@code "/>
 *</bean>
 *}</pre>
 *
 * Example properties file:
 *
 * <pre class="code"> driver=com.mysql.jdbc.Driver
 * dbname=mysql:mydb</pre>
 *
 * Annotated bean definitions may take advantage of property replacement using
 * the {@link org.springframework.beans.factory.annotation.Value @Value} annotation:
 *
 *<pre class="code">@Value("${person.age}")</pre>
 *
 * Implementations check simple property values, lists, maps, props, and bean names
 * in bean references. Furthermore, placeholder values can also cross-reference
 * other placeholders, like:
 *
 *<pre class="code">rootPath=myrootdir
 *subPath=${rootPath}/subdir</pre>
 *
 * In contrast to {@link PropertyOverrideConfigurer}, subclasses of this type allow
 * filling in of explicit placeholders in bean definitions.
 *
 * <p>If a configurer cannot resolve a placeholder, a {@link BeanDefinitionStoreException}
 * will be thrown. If you want to check against multiple properties files, specify multiple
 * resources via the {@link #setLocations locations} property. You can also define multiple
 * configurers, each with its <em>own</em> placeholder syntax. Use {@link
 * #ignoreUnresolvablePlaceholders} to intentionally suppress throwing an exception if a
 * placeholder cannot be resolved.
 *
 * <p>Default property values can be defined globally for each configurer instance
 * via the {@link #setProperties properties} property, or on a property-by-property basis
 * using the default value separator which is {@code ":"} by default and
 * customizable via {@link #setValueSeparator(String)}.
 *
 * <p>Example XML property with default value:
 *
 *<pre class="code">{@code
 *  <property name="url" value="jdbc:}${dbname:defaultdb}{@code "/>
 *}</pre>
 *
 * @author Chris Beams
 * @author Juergen Hoeller
 * @since 3.1
 * @see PropertyPlaceholderConfigurer
 * @see org.springframework.context.support.PropertySourcesPlaceholderConfigurer
 */
public abstract class PlaceholderConfigurerSupport extends PropertyResourceConfigurer
      implements BeanNameAware, BeanFactoryAware {

   /** Default placeholder prefix: {@value} */
   public static final String DEFAULT_PLACEHOLDER_PREFIX = "${";

   /** Default placeholder suffix: {@value} */
   public static final String DEFAULT_PLACEHOLDER_SUFFIX = "}";

   /** Default value separator: {@value} */
   public static final String DEFAULT_VALUE_SEPARATOR = ":";


   /** Defaults to {@value #DEFAULT_PLACEHOLDER_PREFIX} */
   protected String placeholderPrefix = DEFAULT_PLACEHOLDER_PREFIX;

   /** Defaults to {@value #DEFAULT_PLACEHOLDER_SUFFIX} */
   protected String placeholderSuffix = DEFAULT_PLACEHOLDER_SUFFIX;

   /** Defaults to {@value #DEFAULT_VALUE_SEPARATOR} */
   protected String valueSeparator = DEFAULT_VALUE_SEPARATOR;

   protected boolean ignoreUnresolvablePlaceholders = false;

   protected String nullValue;

   private BeanFactory beanFactory;

   private String beanName;

 

類註釋表示的是,該類所起的做用,替代了xml文件的哪些操做,咱們只須要看下面定義的一個常量註解就能大概知道,爲何須要返回這麼一個bean了.url

類註釋上有這麼一句話:表示能夠用帶註釋的bean,能夠利用屬性符號進行替換spa

* Annotated bean definitions may take advantage of property replacement using
* the {@link org.springframework.beans.factory.annotation.Value @Value} annotation:
*
*<pre class="code">@Value("${person.age}")</pre>

 

屬性註釋:

/** Default placeholder prefix: {@value} */
public static final String DEFAULT_PLACEHOLDER_PREFIX = "${";

/** Default placeholder suffix: {@value} */
public static final String DEFAULT_PLACEHOLDER_SUFFIX = "}";

/** Default value separator: {@value} */
public static final String DEFAULT_VALUE_SEPARATOR = ":";


/** Defaults to {@value #DEFAULT_PLACEHOLDER_PREFIX} */
protected String placeholderPrefix = DEFAULT_PLACEHOLDER_PREFIX;

/** Defaults to {@value #DEFAULT_PLACEHOLDER_SUFFIX} */
protected String placeholderSuffix = DEFAULT_PLACEHOLDER_SUFFIX;

/** Defaults to {@value #DEFAULT_VALUE_SEPARATOR} */
protected String valueSeparator = DEFAULT_VALUE_SEPARATOR;

protected boolean ignoreUnresolvablePlaceholders = false;

 

從上面註解能夠發現,使用的 默認前綴是:  '${',  然後綴是:  '}' ,默認的分隔符是 ':', 可是set方法能夠替換掉默認的分隔符,而 ignoreUnresolvablePlaceholders 默認爲 false,表示會開啓配置文件不存在,拋出異常的錯誤.

從上面就能看出這個bean所起的做用,就是將@propertySource註解的bean注入屬性的做用,若是沒有該bean,則不能解析${}符號.

 

下面是測試執行方法:

@Configuration
//掃描帶有 @controller @service @Component 等spring註解的類註冊爲bean
@ComponentScan({"com.spring.annotation.annotationsAttribute"})
public class AnnotationsConfig {
   public static void main(String[] args){
      AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AnnotationsConfig.class);

      DemoAnnotation demoAnnotation = context.getBean(DemoAnnotation.class);

      System.out.println(demoAnnotation.toString());

      context.close();
   }
}

 

打印結果爲:

 

這就表示,咱們的注入成功了

 

 

使用 @PropertySource註解須要注意如下幾個地方

  1. 使用註解須要將類申明被掃描爲一個bean,可使用@Component 註解

  2. @PropertySource(value = "classpath:properties/config_userbean.properties",ignoreResourceNotFound = true) 表示注入配置文件,而且忽略配置文件不存在的異常

  3. 必須返回一個 PropertySourcesPlaceholderConfigurer 的bean,不然,會不能識別@Value("${userBean.name}") 註解中的 ${userBean.name}指向的value,而會注入${userBean.name}的字符串,返回 PropertySourcesPlaceholderConfigurer 的方法,使用@Bean註解,表示返回的是個bean

 

 

在spring 4.0之後,spring增長了@PropertySources 註解,下面是源碼

 

/**
 * Container annotation that aggregates several {@link PropertySource} annotations.
 *
 * <p>Can be used natively, declaring several nested {@link PropertySource} annotations.
 * Can also be used in conjunction with Java 8's support for <em>repeatable annotations</em>,
 * where {@link PropertySource} can simply be declared several times on the same
 * {@linkplain ElementType#TYPE type}, implicitly generating this container annotation.
 *
 * @author Phillip Webb
 * @since 4.0
 * @see PropertySource
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PropertySources {

   PropertySource[] value();

}

 

從源碼的註釋,能夠看到自4.0之後,@PropertySources註解,可使用多個@PropertySource註解,代碼以下:

@PropertySources(
      {
            @PropertySource("classpath:properties/config_userbean.properties"),
            @PropertySource("classpath:properties/config_mysql.properties")
      }
)

 

 

有時候使用@PropertySource 註解會報 找不到這個註解的錯誤,可是spring確實是3.1以上版本,並且並不影響項目的使用,這樣的話,可使用@propertySources 註解嵌套@propertySource註解,這樣就不會報錯了

 

以上,均爲本人測試而得出的結果,可能會有出入,或者錯誤,歡迎指正

 

歡迎轉載,請註明出處跟做者,謝謝!

相關文章
相關標籤/搜索