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註解須要注意如下幾個地方
使用註解須要將類申明被掃描爲一個bean,可使用@Component 註解
@PropertySource(value = "classpath:properties/config_userbean.properties",ignoreResourceNotFound = true) 表示注入配置文件,而且忽略配置文件不存在的異常
必須返回一個 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註解,這樣就不會報錯了
以上,均爲本人測試而得出的結果,可能會有出入,或者錯誤,歡迎指正
歡迎轉載,請註明出處跟做者,謝謝!