您好,登錄后才能下訂單哦!
SpringBoot中有哪些注入數據的方式?相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
1.不通過配置文件注入數據
通過@Value將外部的值動態注入到Bean中,使用的情況有:
注入普通字符串
注入操作系統屬性
注入表達式結果
注入其他Bean屬性:注入Student對象的屬性name
注入文件資源
注入URL資源
輔助代碼
package com.hannpang.model; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component(value = "st")//對student進行實例化操作 public class Student { @Value("悟空") private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
測試@Value的代碼
package com.hannpang.model; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.Resource; import org.springframework.stereotype.Component; @Component public class SimpleObject { @Value("注入普通字符串") private String normal; //關于屬性的KEY可以查看System類說明 @Value("#{systemProperties['java.version']}")//-->使用了SpEL表達式 private String systemPropertiesName; // 注入操作系統屬性 @Value("#{T(java.lang.Math).random()*80}")//獲取隨機數 private double randomNumber; //注入表達式結果 @Value("#{1+2}") private double sum; //注入表達式結果 1+2的求和 @Value("classpath:os.yaml") private Resource resourceFile; // 注入文件資源 @Value("http://www.baidu.com") private Resource testUrl; // 注入URL資源 @Value("#{st.name}") private String studentName; //省略getter和setter方法 @Override public String toString() { return "SimpleObject{" + "normal='" + normal + '\'' + ", systemPropertiesName='" + systemPropertiesName + '\'' + ", randomNumber=" + randomNumber + ", sum=" + sum + ", resourceFile=" + resourceFile + ", testUrl=" + testUrl + ", studentName='" + studentName + '\'' + '}'; } }
Spring的測試代碼
package com.hannpang; import com.hannpang.model.SimpleObject; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class Demo04BootApplicationTests { @Autowired private SimpleObject so; @Test public void contextLoads() { System.out.println(so); } }
運行結果為:SimpleObject{normal='注入普通字符串', systemPropertiesName='1.8.0_172', randomNumber=56.631954541947266, sum=3.0, resourceFile=class path resource [os.yaml], testUrl=URL [http://www.baidu.com], studentName='悟空'}
2.通過配置文件注入數據
通過@Value將外部配置文件的值動態注入到Bean中。配置文件主要有兩類:
application.properties、application.yaml application.properties在spring boot啟動時默認加載此文件
自定義屬性文件。自定義屬性文件通過@PropertySource加載。@PropertySource可以同時加載多個文件,也可以加載單個文件。如果相同第一個屬性文件和第二屬性文件存在相同key,則最后一個屬性文件里的key啟作用。加載文件的路徑也可以配置變量,如下文的${anotherfile.configinject},此值定義在第一個屬性文件config.properties
在application.properties中加入如下測試代碼
app.name=一步教育
在resources下面新建第一個屬性文件config.properties
內容如下
book.name=西游記 anotherfile.configinject=system
在resources下面新建第二個屬性文件config_system.properties
內容如下
我的目的是想system的值使用第一個屬性文件中定義的值
book.name.author=吳承恩
下面通過@Value(“${app.name}”)
語法將屬性文件的值注入bean屬性值,詳細代碼見:
package com.hannpang.test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.PropertySource; import org.springframework.core.env.Environment; import org.springframework.stereotype.Component; @Component @PropertySource(value = {"classpath:config.properties","classpath:config_${anotherfile.configinject}.properties"}) public class LoadPropsTest { @Value("${app.name}") private String appName; // 這里的值來自application.properties,spring boot啟動時默認加載此文件 @Value("${book.name}") private String bookName; // 注入第一個配置外部文件屬性 @Value("${book.name.author}") private String author; // 注入第二個配置外部文件屬性 @Autowired private Environment env; // 注入環境變量對象,存儲注入的屬性值 //省略getter和setter方法 public void setAuthor(String author) { this.author = author; } @Override public String toString(){ StringBuilder sb = new StringBuilder(); sb.append("bookName=").append(bookName).append("\r\n") .append("author=").append(author).append("\r\n") .append("appName=").append(appName).append("\r\n") .append("env=").append(env).append("\r\n") // 從eniroment中獲取屬性值 .append("env=").append(env.getProperty("book.name.author")).append("\r\n"); return sb.toString(); } }
測試代碼
package com.hannpang; import com.hannpang.model.SimpleObject; import com.hannpang.test.LoadPropsTest; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class Demo04BootApplicationTests { @Autowired private LoadPropsTest lpt; @Test public void loadPropertiesTest() { System.out.println(lpt); } }
運行結果為:
bookName=西游記
author=吳承恩
appName=一步教育
env=StandardEnvironment {activeProfiles=[], defaultProfiles=[default], propertySources=[ConfigurationPropertySourcesPropertySource {name='configurationProperties'}, MapPropertySource {name='Inlined Test Properties'}, MapPropertySource {name='systemProperties'}, OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}, RandomValuePropertySource {name='random'}, OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.properties]'}, ResourcePropertySource {name='class path resource [config_system.properties]'}, ResourcePropertySource {name='class path resource [config.properties]'}]}
env=吳承恩
3. #{...}和${...}的區別演示
A .${…}
的用法
{}里面的內容必須符合SpEL表達式,通過@Value(“${app.name}”)
可以獲取屬性文件中對應的值,但是如果屬性文件中沒有這個屬性,則會報錯。可以通過賦予默認值解決這個問題,如@Value("${app.name:胖先森}")
部分代碼
// 如果屬性文件沒有app.name,則會報錯 // @Value("${app.name}") // private String name; // 使用app.name設置值,如果不存在則使用默認值 @Value("${app.name:胖先森}") private String name;
B.#{...}
的用法
部分代碼直接演示
// SpEL:調用字符串Hello World的concat方法 @Value("#{'Hello World'.concat('!')}") private String helloWorld; // SpEL: 調用字符串的getBytes方法,然后調用length屬性 @Value("#{'Hello World'.bytes.length}") private String helloWorldbytes;
C.#{...}
和${...}
混合使用
${...}和#{...}
可以混合使用,如下文代碼執行順序:通過${server.name}從屬性文件中獲取值并進行替換,然后就變成了 執行SpEL表達式{‘server1,server2,server3'.split(‘,')}。
// SpEL: 傳入一個字符串,根據","切分后插入列表中, #{}和${}配置使用(注意單引號,注意不能反過來${}在外面,#{}在里面) @Value("#{'${server.name}'.split(',')}") private List<String> servers;
在上文中在#{}外面,${}在里面
可以執行成功,那么反過來是否可以呢${}在外面,#{}在里面
,如代碼
// SpEL: 注意不能反過來${}在外面,#{}在里面,這個會執行失敗 @Value("${#{'HelloWorld'.concat('_')}}") private List<String> servers2;
答案是不能。
因為spring執行${}是時機要早于#{}。
在本例中,Spring會嘗試從屬性中查找#{‘HelloWorld'.concat(‘_')},那么肯定找到,由上文已知如果找不到,然后報錯。所以${}在外面,#{}在里面是非法操作
D.用法總結
#{…} 用于執行SpEl表達式,并將內容賦值給屬性
${…} 主要用于加載外部屬性文件中的值
#{…} 和${…} 可以混合使用,但是必須#{}外面,${}在里面
4.@Value獲取值和@ConfigurationProperties獲取值比較
@ConfigurationProperties | @Value | |
---|---|---|
功能 | 批量注入配置文件中的屬性 | 一個個指定 |
松散綁定(松散語法) | 支持 | 不支持 |
SpEL | 不支持 | 支持 |
JSR303數據校驗 | 支持 | 不支持 |
復雜類型封裝 | 支持 | 不支持 |
配置文件yml還是properties他們都能獲取到值;
如果說,我們只是在某個業務邏輯中需要獲取一下配置文件中的某項值,使用@Value;
如果說,我們專門編寫了一個javaBean來和配置文件進行映射,我們就直接使用@ConfigurationProperties;
關于數據校驗的部分代碼
@Component @ConfigurationProperties(prefix = "person") @Validated public class Person { //lastName必須是郵箱格式 @Email private String lastName;
5. @ImportResource引入配置文件
不推薦的使用方式
Spring Boot里面沒有Spring的配置文件,我們自己編寫的配置文件,也不能自動識別;
想讓Spring的配置文件生效,加載進來;@ImportResource標注在一個配置類上
@ImportResource(locations = {"classpath:beans.xml"}) 導入Spring的配置文件讓其生效
編寫配置文件信息
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="helloService" class="com.hanpang.springboot.service.HelloService"></bean> </beans>
大概了解就好,我們基本上不使用這種方式
6.@Configuration注解
SpringBoot推薦給容器中添加組件的方式;推薦使用全注解的方式
1、配置類@Configuration
作用于類上,相當于一個xml配置文件
2、使用@Bean
給容器中添加組件,作用于方法上
/** * @Configuration:指明當前類是一個配置類;就是來替代之前的Spring配置文件 * * 在配置文件中用<bean><bean/>標簽添加組件 * <bean id="helloService" class="com.hanpang.springboot.service.HelloService"></bean> */ @Configuration public class MyAppConfig { //將方法的返回值添加到容器中;容器中這個組件默認的id就是方法名 @Bean public HelloService helloService02(){ System.out.println("配置類@Bean給容器中添加組件了..."); return new HelloService(); } }
使用Bean注入太麻煩,我們更加喜歡使用掃描的方式
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import com.wx.dao.IUserDao; import com.wx.dao.UserDaoImpl; //通過該注解來表明該類是一個Spring的配置,相當于一個傳統的ApplicationContext.xml @Configuration //相當于配置文件里面的<context:component-scan/>標簽,掃描這些包下面的類的注解 @ComponentScan(basePackages="com.hanpang.dao,com.hanpang.service") public class SpringConfig { // 通過該注解來表明是一個Bean對象,相當于xml中的<bean> //bean的id值默認是方法名userDao /* @Bean public HelloService helloService02(){ System.out.println("配置類@Bean給容器中添加組件了..."); return new HelloService(); } */ }
附錄
隨機數
${random.value}、${random.int}、${random.long} ${random.int(10)}、${random.int[1024,65536]}
看完上述內容,你們掌握SpringBoot中有哪些注入數據的方式的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。