Spring注入需要初始化,但前面均使用硬編碼注入,如:
JavaConfig配置:
1 package soundSystem; 2 3 import org.springframework.stereotype.Component; 4 5 /** 6 * CompactDisc接口的實現類,此類中定義了CD的名字和作者以及打印相關信息的方法 7 * @author yan 8 */ 9 @Component("compactd")//用於掃描來動態生成bean 10 public class SgtPeppers implements CompactDisc{ 11 12 private String title="K歌之王"; 13 private String artist="陳奕迅"; 14 @Override 15 public void cdInfo() { 16 System.out.print("This CD's title:"+title+";artist:"+artist); 17 } 18 19 }
xml配置(需要實現setter方法):
1 <bean id="cd" class="soundSystem.SgtPeppers"> 2 <property name="title" value="L.O.V.E"></property> 3 <property name="artist" value="May Day"></property> 4 </bean>
Spring允許注入外部值,這樣不用受到硬編碼的限制:
--JavaConfig(顯式bean)
主要是在配置類中實現:
1.在配置類類名上方添加注解@PropertySource("classpath:/sp.properties"),參數為文件全路徑名,properties文件是專門用來存放k-v值對的;
2.在配置類中定義Environment env,並添加@AutoWired注解;
3.在定義bean的方法中使用env.getProperty()方法配置文件(*.properties)中的值來賦給bean作為參數。
1 package com.spring.config; 2 3 import org.springframework.beans.factory.annotation.Autowired; 4 import org.springframework.context.annotation.Bean; 5 import org.springframework.context.annotation.ComponentScan; 6 import org.springframework.context.annotation.Configuration; 7 import org.springframework.context.annotation.PropertySource; 8 import org.springframework.core.env.Environment; 9 10 import com.spring.custom.Person; 11 12 @Configuration("com.spring.custom") 13 @ComponentScan(basePackages={"com.spring"}) 14 @PropertySource("classpath:/sp.properties") 15 public class CreatureSpingConfig { 16 @Autowired 17 Environment env; 18 @Bean 19 public Person person(){ 20 return new Person(env.getProperty("name"), env.getProperty("age",Integer.class), env.getProperty("sex")); 21 } 22 }
這樣就實現了從外部文件注入的目標了。
注:getProperty("key值")返回的是String類型,但並不是所有參數都是String類型,所以這個方法有幾個重載形式
解釋如下:
1 public interface PropertyResolver { 2 3 //是否包含某個屬性 4 boolean containsProperty(String key); 5 6 //獲取屬性值 如果找不到返回null 7 String getProperty(String key); 8 9 //獲取屬性值,如果找不到返回默認值 10 String getProperty(String key, String defaultValue); 11 12 //獲取指定類型的屬性值,找不到返回null 13 <T> T getProperty(String key, Class<T> targetType); 14 15 //獲取指定類型的屬性值,找不到返回默認值 16 <T> T getProperty(String key, Class<T> targetType, T defaultValue); 17 18 //獲取屬性值為某個Class類型,找不到返回null,如果類型不兼容將拋出ConversionException 19 <T> Class<T> getPropertyAsClass(String key, Class<T> targetType); 20 21 //獲取屬性值,找不到拋出異常IllegalStateException 22 String getRequiredProperty(String key) throws IllegalStateException; 23 24 //獲取指定類型的屬性值,找不到拋出異常IllegalStateException 25 <T> T getRequiredProperty(String key, Class<T> targetType) throws IllegalStateException; 26 27 //替換文本中的占位符(${key})到屬性值,找不到不解析 28 String resolvePlaceholders(String text); 29 30 //替換文本中的占位符(${key})到屬性值,找不到拋出異常IllegalArgumentException 31 String resolveRequiredPlaceholders(String text) throws IllegalArgumentException; 32 33 }
這里列舉的是PropertyResolver接口中定義的方法,是因為Environment繼承了這個接口,上例中我們使用了第7行和第13行的getProperty的兩種重載的形式,當然也可是設置默認值。
--JavaConfig(注解生成bean)演示@Value注解使用方式
實現類:
1 package com.spring.beans; 2 3 import org.springframework.beans.factory.annotation.Autowired; 4 import org.springframework.beans.factory.annotation.Value; 5 import org.springframework.stereotype.Component; 6 @Component//自動生成bean 7 public class VCD implements CompactDisc{ 8 9 private String title; 10 private String artist; 11 private int year; 12 13 //定義有參構造 14 @Autowired//必須寫,不寫會報錯(目前不知原因) 15 public VCD(@Value("${title}")String title, @Value("${artist}")String artist,@Value("${year}")int year) { 16 super(); 17 this.title = title; 18 this.artist = artist; 19 this.year=year;} 20 @Override 21 public void play() { 22 System.out.println("Playing CD's title is"+title+",the artist is"+artist+",the year is"+year); 23 } 24 }
配置類:
1 package com.spring.config; 2 3 import org.springframework.beans.factory.annotation.Autowired; 4 import org.springframework.beans.factory.annotation.Configurable; 5 import org.springframework.context.annotation.Bean; 6 import org.springframework.context.annotation.ComponentScan; 7 import org.springframework.context.annotation.Configuration; 8 //import org.springframework.context.annotation.ImportResource; 9 import org.springframework.context.annotation.PropertySource; 10 import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; 11 import org.springframework.core.env.Environment; 12 13 14 @Configuration//表明這是一個Spring的配置類 15 @ComponentScan(value="com.spring")//表示需要掃描的包,因為演示所用為顯式bean,所以其實這里沒必要添加此注解 16 @PropertySource(value="classpath:propertiesSource.properties") 17 //@ImportResource("classpath:spring.xml")//引入XML配置文件 18 public class SpringConfig { 19 /** 20 * 因為采用混合配置,故注釋掉重復bean及無用變量 21 */ 22 @Autowired 23 private Environment e; 24 25 @Bean//要使用@Value注解需要添加此bean 26 public static PropertySourcesPlaceholderConfigurer pc(){ 27 return new PropertySourcesPlaceholderConfigurer(); 28 } 29 }
配置文件:
title=L.O.V.E artist=May Day year=2006
注:
- 要使用@Value需要添加PropertySourcesPlaceholderConfigurer類的bean;
- 需要在使用@Value處添加@AutoWired注解,否則會出錯。
--XML(顯式bean)
此處使用混合配置,以CD為例。
配置類:
1 package com.spring.config; 2 3 //import org.springframework.beans.factory.annotation.Autowired; 4 //import org.springframework.beans.factory.annotation.Configurable; 5 //import org.springframework.context.annotation.Bean; 6 import org.springframework.context.annotation.ComponentScan; 7 import org.springframework.context.annotation.Configuration; 8 import org.springframework.context.annotation.ImportResource; 9 //import org.springframework.context.annotation.PropertySource; 10 //import org.springframework.core.env.Environment; 11 12 13 @Configuration//表明這是一個Spring的配置類 14 @ComponentScan(value="com.spring")//表示需要掃描的包,因為演示所用為顯式bean,所以其實這里沒必要添加此注解 15 //@PropertySource(value="classpath:propertiesSource.properties") 16 @ImportResource("classpath:spring.xml")//引入XML配置文件 17 public class SpringConfig { 18 /** 19 * 因為采用混合配置,故注釋掉重復bean及無用變量 20 */ 21 // @Autowired 22 // private Environment e; 23 24 // @Bean 25 // public CompactDisc cd(){ 26 // return new VCD(e.getProperty("title"),e.getProperty("artist")); 27 // } 28 }
實現類:
1 package com.spring.beans; 2 public class VCD implements CompactDisc{ 3 4 private String title; 5 private String artist; 6 private int year; 7 //定義有參構造 8 public VCD(String title, String artist,int year) { 9 super(); 10 this.title = title; 11 this.artist = artist; 12 this.year=year; 13 System.out.println("Playing CD's title is"+this.title+",the artist is"+this.artist+",the year is"+this.year);} 14 @Override 15 public void play() {} 16 }
在XML中:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:c="http://www.springframework.org/schema/c" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd "> <context:property-placeholder location="classpath:propertiesSource.properties"/> <bean id="cd" class="com.spring.beans.VCD" c:_0="${title}" c:_1="${artist}" c:_2="${year}"> </bean> </beans>
配置文件中:
title=L.O.V.E
artist=May Day
year=2006
這樣便可以實現從外部注入屬性值了。
注意:
- 在XML配置中,要添加<context:property-placeholder/>標簽,其屬性location的值便為配置文件的路徑,這與JavaConfig中的@PropertySource起同樣的作用;
- 從例子中可以看出,構造器注入,可以使用c-命名空間來設置初始值,格式如:c:_index,index為構造器中參數的索引值,從0開始。而<context:property-placeholder/>標簽是專門用來匹配屬性占位符的,缺少此標簽則不起作用。
2016-10-25 21:20:52
資料參考: