<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
有引數檔案如下test.properties
project.author=wpfc project.create_time=2018/3/29
在系統中讀取對應的資料,並注入到屬性中
@Configuration @ComponentScan("cn.edu.ntu") @PropertySource("classpath:test.properties") public class ElConfig { @Value("#{systemProperties['os.name']}") private String osName; //要想使用@Value 用${}預留位置注入屬性,這個bean是必須的(PropertySourcesPlaceholderConfigurer), //這個就是佔位bean, //另一種方式是不用value直接用Envirment變數直接getProperty('key') @Value("${project.author}") public String author; @Autowired private Environment environment; //You need this if you use @PropertySource + @Value @Bean public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { return new PropertySourcesPlaceholderConfigurer(); } public void printProperties(){ System.out.println("os name : " + osName); System.out.println("author : " + author); System.out.println("env : " + environment.getProperty("project.create_time")); } }
測試方法:
public class MainApplication { public static void main(String[] args){ AnnotationConfigApplicationContext context = null; context = new AnnotationConfigApplicationContext(ElConfig.class); ElConfig bean = context.getBean(ElConfig.class); bean.printProperties(); } }
測試結果:
os name : Windows 7
author : wpfc
env : 2018/3/29
@Import
引入javaConfig設定的設定類@ImportResource
引入xml對應的組態檔Spring (Boot)獲取引數的方式有很多,其中最被我們熟知的為@Value了,它不可謂不強大。
今天就針對我們平時最長使用的@Value,以及可能很少人使用的@PropertySource、@ConfigurationProperties等相關注解進行一個詳細的掃盲,希望能夠幫助到到家,使用起來更加順暢
@Value註解的注入非常強大,可以藉助組態檔的注入、也可以直接注入
注入普通字串
@Value("normal") private String normal; // normal (顯然這種注入的意義不大)
注入作業系統屬性
@Value("#{systemProperties['os.name']}") private String systemPropertiesName; //效果等同於 是因為spring模版把系統變數否放進了Enviroment @Value("${os.name}") private String systemPropertiesName;
注入表示式結果
@Value("#{ T(java.lang.Math).random() * 100.0 }") private double randomNumber; //41.29185128620939
注入其它Bean的屬性:Person類的name屬性
@Bean public Person person() { Person person = new Person(); person.setName("fangshixiang"); return person; } //注入屬性 @Value("#{person.name}") private String personName; @Test public void contextLoads() { System.out.println(personName); //fangshixiang }
注入檔案資源
在resources下放置一個jdbc.properties組態檔。然後可以直接注入
@Value("classpath:jdbc.properties") private Resource resourceFile; // 注入檔案資源 @Test public void contextLoads() throws IOException { System.out.println(resourceFile); //class path resource [jdbc.properties] String s = FileUtils.readFileToString(resourceFile.getFile(), StandardCharsets.UTF_8); System.out.println(s); //輸出: //db.username=fangshixiang //db.password=fang //db.url=jdbc:mysql://localhost:3306/mytest //db.driver-class-name=com.mysql.jdbc.Driver }
注入Url資源
@Value("http://www.baidu.com") private Resource testUrl; // 注入URL資源 @Test public void contextLoads() { System.out.println(testUrl); //URL [http://www.baidu.com] }
語法:
${ properties }和#{ SpEL }的語法區別
${ property : default_value }
#{ obj.property? : default_value } 表示SpEl表示式通常用來獲取bean的屬性,或者呼叫bean的某個方法。當然還有可以表示常數
正常使用的情況,這裡不做過多的介紹了,現在介紹一些異常情況
${ properties }`:這種比較簡單,如果key找不到,啟動會失敗。如果找不到的時候也希望正常啟動,可以採用冒號+預設值的方式
#{ obj.property? : default_value }
@Value("#{person}") private Person value; @Test public void contextLoads() { System.out.println(value); //Person(name=fangshixiang, age=null, addr=null, hobby=null) }
我們發現這個很強大,可以直接把容器的裡的一個物件直接注入進來。只是我們可能一般不這麼做。
如果改成person1,在容器裡找不到這個bean,也是會啟動報錯的。@Value("#{person1?:null}")這樣也是不行的,因為person1找不到就會報錯
@Value("#{person.name}") private String personName; @Value("#{person.age}") private String perAge; //注入預設值 @Value("#{person.age?:20}") private String perAgeDefault; //如果age22這個key根本就不存在,啟動肯定會報錯的 //@Value("#{person.age22?:20}") //private String perAgeDefault22; @Test public void contextLoads() { System.out.println(personName); //fangshixiang System.out.println(perAge); //null System.out.println(perAgeDefault); //20 }
獲取級聯屬性,下面兩種方法都是ok的:
@Value("#{person.parent.name}") private String parentName1; @Value("#{person['parent.name']}") private String parentName2; @Test public void contextLoads() { System.out.println(parentName1); //fangshixiang System.out.println(parentName2); //fangshixiang }
二者結合使用:#{ ‘${}’ }
注意結合使用的語法和單引號,不能倒過來。
兩者結合使用,可以利用SpEL的特性,寫出一些較為複雜的表示式,如:
@Value("#{'${os.name}' + '_' + person.name}") private String age; @Test public void contextLoads() { System.out.println(age); //Windows 10_fangshixiang }
此註解也是非常非常的強大,用好了,可以很好的實現組態檔的分離關注,大大提高開發的效率,實現集中化管理
最簡單的應用,結合@Value注入屬性值(也是最常見的應用)
通過@PropertySource把組態檔載入進來,然後使用@Value獲取
@Configuration @PropertySource("classpath:jdbc.properties") public class PropertySourceConfig { @Value("${db.url}") private String dbUrl; @PostConstruct public void postConstruct() { System.out.println(dbUrl); //jdbc:mysql://localhost:3306/mytest } }
@PropertySource各屬性介紹
value
:陣列。指定組態檔的位置。支援classpath:和file:等字首 Spring發現是classpath開頭的,因此最終使用的是Resource的子類ClassPathResource。如果是file開頭的,則最終使用的類是FileSystemResourceignoreResourceNotFound
:預設值false。表示如果沒有找到檔案就報錯,若改為true就不報錯。建議保留falseencoding
:載入進來的編碼。一般不用設定,可以設定為UTF-8等等factory
:預設的值為DefaultPropertySourceFactory.class。@Override public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException { return (name != null ? new ResourcePropertySource(name, resource) : new ResourcePropertySource(resource)); }
原始碼其實也沒什麼特別的。其重難點在於:
1、DefaultPropertySourceFactory什麼時候被Spring載入呢?
2、name和resource都是什麼時候被賦值進來的?
本文丟擲這兩個問題,具體原因會在後續分析原始碼的相關文章中有所體現。
需要注意的是PropertySourceFactory的載入時機早於Spring Beans容器,因此實現上不能依賴於Spring的IOC。
@PropertySource多環境設定以及表示式使用(spring.profiles.active)
方法一:可以這麼設定
@PropertySource(「classpath:jdbc-${spring.profiles.active}.properties」)
程式設計師在開發時不需要關心生產環境資料庫的地址、賬號等資訊,一次構建即可在不同環境中執行
注意:上面其實都是Spring Framwork提供的功能。而@ConfigurationProperties是Spring Boot提供的。包括@EnableConfigurationProperties也是Spring Boot才有的。它在自動化設定中起到了非常關鍵的作用
ConfigurationPropertiesBindingPostProcessor會對標註@ConfigurationProperties註解的Bean進行屬性值的設定。
有時候有這樣子的情景,我們想把組態檔的資訊,讀取並自動封裝成實體類,這樣子,我們在程式碼裡面使用就輕鬆方便多了,這時候,我們就可以使用@ConfigurationProperties,它可以把同類的設定資訊自動封裝成實體類
該註解在Spring Boot的自動化設定中得到了大量的使用
如SpringMVC的自動化設定:
@ConfigurationProperties(prefix = "spring.mvc") public class WebMvcProperties {} //載入方式 @Configuration @Conditional(DefaultDispatcherServletCondition.class) @ConditionalOnClass(ServletRegistration.class) // 此處採用這個註解,可議把WebMvcProperties這個Bean載入到容器裡面去~~~ // WebMvcProperties裡面使用了`@ConfigurationProperties(prefix = "spring.mvc")` @EnableConfigurationProperties(WebMvcProperties.class) //載入MVC的組態檔 protected static class DispatcherServletConfiguration {}
似乎我們能看出來一些該註解的使用方式。
說明:這裡說的兩種,只是說的最常用的。其實只要能往容器注入Bean,都是一種方式,比如上面的@EnableConfigurationProperties方式也是ok的
關於@EnableConfigurationProperties的解釋,在註解驅動的Spring相關博文裡會有體現
加在類上,需要和@Component註解,結合使用.程式碼如下
com.example.demo.name=${aaa:hi} com.example.demo.age=11 com.example.demo.address[0]=北京 # 注意陣列 List的表示方式 Map/Obj的方式各位可以自行嘗試 com.example.demo.address[1]=上海 com.example.demo.address[2]=廣州 com.example.demo.phone.number=1111111
java程式碼:
@Component @ConfigurationProperties(prefix = "com.example.demo") public class People { private String name; private Integer age; private List<String> address; private Phone phone; }
通過@Bean的方式進行宣告,這裡我們加在啟動類即可,程式碼如下
@Bean @ConfigurationProperties(prefix = "com.example.demo") public People people() { return new People(); }
此些方式並不需要使用@EnableConfigurationProperties去開啟它。
細節:Bean的欄位必須有get/set方法,請注意~~~
另外還有一種結合@PropertySource使用的方式,可謂完美搭配
@Component @PropertySource("classpath:config/object.properties") @ConfigurationProperties(prefix = "obj") public class ObjectProperties {}
其餘屬性見名之意,這裡一筆帶過:
ignoreInvalidFields
ignoreNestedProperties
ignoreUnknownFields
簡單理解:
@ConfigurationProperties
是將application組態檔的某類名下所有的屬性值,自動封裝到實體類中。@Value
是將application組態檔中,所需要的某個屬性值,封裝到java程式碼中以供使用。應用場景不同:
如果只是某個業務中需要獲取組態檔中的某項值或者設定具體值,可以使用@Value;
如果一個JavaBean中大量屬性值要和組態檔進行對映,可以使用@ConfigurationProperties;
以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45