不會使用Spring的配置檔案,趕緊把這個甩給他
摘要:文章從Spring程式的快速使用、Bean標籤的使用和其屬性的具體使用,每個屬性都用程式碼來解釋,執行結果和案例也寫的都很明白。
本文分享自華為雲社群《怎樣使用Spring的配置檔案?帶大家一起玩轉Spring配置檔案》,作者:我是一棵捲心菜 。
一、Spring程式快速入門
步驟一:匯入 Spring 開發的基本包座標
建立一個maven工程,匯入Spring需要的依賴,為了方便測試,我還匯入了一個Junit測試包
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.14</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
步驟二:編寫 Dao 介面和實現類
接下里,需要編寫一個Dao介面和其實現類,用來搭建測試的環境,話多不說,直接上程式碼
public interface UserDao {
void save();
}
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("儲存成功~~");
}
}
步驟三:建立 Spring 核心配置檔案
介面和類寫完後,就開始進入正題,在類路徑下(resources)建立Spring的核心配置檔案,我取名為applicationContext.xml
<?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">
</beans>
步驟四:在 Spring 配置檔案中配置 UserDaoImpl類
建立好xml配置檔案後,我要想呼叫save()方法,就需要建立UserDaoImpl類的物件,這裡採用容器的方式。
<bean id="userdao" class="com.sht.dao.impl.UserDaoImpl"></bean>
這裡的id是自定義的,最好是類名的首字母小寫,方便於記憶。class屬性值是要建立類物件的所在包路徑,我的這個UserDaoImpl類所在的包路徑就是com.sht.dao.impl.UserDaoImpl,這一點都不能寫錯哦!
步驟五:使用 Spring 的 API 獲得 Bean 例項
接下來測試一下:
public class UserDaoDemo {
public static void main(String[] args) {
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userdao = (UserDao) applicationContext.getBean("userdao");
userdao.save();
}
}
通過new ClassPathXmlApplicationContext("applicationContext.xml")獲取到容器——applicationContext,然後通過id對應的屬性值獲取到UserDaoImpl類的物件,這樣我們就不需要用new的方式來建立物件了!
以上java程式碼還可以寫成另一種方式:
public class UserDaoDemo {
public static void main(String[] args) {
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
UserDaoImpl userDao = applicationContext.getBean(UserDaoImpl.class);
userDao.save();
}
}
其中,當引數的資料型別是字串時,表示根據Bean的id從容器中獲得Bean例項,返回是Object,需要強轉。
當引數的資料型別是Class型別時,表示根據型別從容器中匹配Bean例項,特別注意的是:當容器中相同型別的Bean有多個時,則此方法會報錯。
執行結果:
結果正確,到了這裡,spring的配置檔案你已經有了基本的瞭解,接下來讓我們看看spring配置檔案中其它的細節使用吧!
二、Spring配置檔案使用
1、Bean標籤基本配置
基本介紹
用於配置物件交由Spring 來建立
預設情況下它呼叫的是類中的無參建構函式,如果沒有無參建構函式則不能建立成功,對於有參構造器,後面會慢慢講到
基本屬性
id:Bean例項在Spring容器中的唯一標識
class:Bean的全限定名稱
這兩個基本屬性在快速入門中已經使用過了,就不最多介紹了
Bean標籤範圍配置(Scope)
修改xml配置檔案,在原來的bean中加入scope="singleton",這就意味著,我們不管建立多少個物件,都是同一個
<bean id="userdao" class="com.sht.dao.impl.UserDaoImpl" scope="singleton"></bean>
寫一個測試程式碼
public void test1(){
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userdao1 = (UserDao) context.getBean("userdao");
System.out.println(userdao1);
UserDao userdao2 = (UserDao) context.getBean("userdao");
System.out.println(userdao2);
System.out.println("是否為同一個物件例項:" + (userdao1 == userdao2));
}
執行結果:
繼續修改xml配置檔案,把scope="singleton"改為scope="prototype",即表明,我們用其建立物件時,不是同一個物件例項
上面的測試程式碼不變,執行結果:
Bean標籤例項化時機
小夥伴們可能就有疑問了,上面這兩種方式是什麼時候建立物件例項的呢?不要急,咱們慢慢道來。
為了方便效果的展現,我在UserDaoImpl類的無參構造器中加入一句程式碼,用來區別建立例項的時機
public UserDaoImpl(){
System.out.println("UserDaoImpl開始建立");
}
scope為singleton時
執行debug,點選F8
我們可以發現,從載入配置檔案的時候就開始建立了物件例項
scope為prototype時
執行debug,按下F8,發現控制檯並沒有列印“UserDaoImpl開始建立”,說明配置檔案並沒有載入物件例項
再次按F8下一步
我們可以發現控制檯終於列印了“UserDaoImpl開始建立”
總結
當scope的取值為singleton時,當應用載入,建立容器時,物件就被建立了;當scope的取值為prototype時,當使用物件時,才建立新的物件例項。
Bean生命週期配置
在UserDaoImpl類中新增兩個方法
public void init(){
System.out.println("初始化方法");
}
public void destory(){
System.out.println("銷燬方法");
}
修改xml配置檔案,init-method:指定類中的初始化方法名稱,destroy-method:指定類中銷燬方法名稱
<bean id="userdao" class="com.sht.dao.impl.UserDaoImpl"
scope="singleton"
init-method="init"
destroy-method="destory">
</bean>
編寫測試程式碼
public void test3(){
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userdao1 = (UserDao) context.getBean("userdao");
System.out.println(userdao1);
UserDao userdao2 = (UserDao) context.getBean("userdao");
System.out.println(userdao2);
System.out.println("是否為同一個物件例項:" + (userdao1 == userdao2));
//這裡用來關閉容器
((ClassPathXmlApplicationContext) context).close();
}
執行結果:
從這個例子,相信大家可以自己推測出建立物件、初始化、方法呼叫以及銷燬的先後順序了
Bean例項化三種方式
方式一:無參構造方法例項化(重點)
其實我們前面一直使用的就是這一種方法,但是需要注意的是,這種方法會根據預設無參構造方法來建立類物件,如果bean中沒有預設無參建構函式,將會建立失敗
方式二:工廠靜態方法例項化(瞭解)
建立一個靜態工廠類,直接返回UserDaoImpl類的物件例項
public class StaticFactory {
public static UserDao getUserDao(){
return new UserDaoImpl();
}
}
編寫xml配置檔案的bean,這裡的class屬性值是靜態工廠類對應的包的路徑,factory-method對應的屬性值是類中的方法名
<bean id="userdao" class="com.sht.factory.StaticFactory" factory-method="getUserDao"></bean>
編寫程式碼測試
public class UserDaoDemo {
public static void main(String[] args) {
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userdao = (UserDao) applicationContext.getBean("userdao");
userdao.save();
}
}
最終的執行結果還會是:“儲存成功~~”
方式三:工廠例項方法例項化(瞭解)
建立一個工廠類,同樣返回UserDaoImpl類的物件例項
public class DynamicFactory {
public UserDao getUserDao(){
return new UserDaoImpl();
}
}
編寫xml配置檔案的bean,這裡的class屬性值是工廠類對應的包的路徑,第一個bean可以得到工廠類的物件,再寫一個bean,用來獲取UserDaoImpl類的物件例項。factory-bean屬性值代表從哪個工廠裡面拿,factory-method對應的屬性值是類中的方法名
<bean id="factory" class="com.sht.factory.DynamicFactory"></bean>
<bean id="userdao" factory-bean="factory" factory-method="getUserDao"></bean>
最終的執行結果也是:“儲存成功~~”
總結
2、Bean的依賴注入
基本介紹
依賴注入(Dependency Injection):它是 Spring 框架核心 IOC 的具體實現。
在編寫程式時,通過控制反轉,把物件的建立交給了 Spring,但是程式碼中不可能出現沒有依賴的情況。IOC 解耦只是降低他們的依賴關係,但不會消除。例如:業務層仍會呼叫持久層的方法。
那這種業務層和持久層的依賴關係,在使用 Spring 之後,就讓 Spring 來維護了。
簡單的說,就是坐等框架把持久層物件傳入業務層,而不用我們自己去獲取。
Bean的依賴注入方式
方式一:有參構造方法
前面講的都是無參構造方法,現在講講有參構造方法。我們先建立一個UserService介面和其實現類UserServiceImpl
public interface UserService {
void save();
}
public class UserServiceImpl implements UserService {
private UserDao userdao;
public UserServiceImpl(UserDao userdao) {
this.userdao = userdao;
}
@Override
public void save() {
userdao.save();
}
}
編寫xml配置檔案的bean,class屬性值分別對應類下的包路徑。<constructor-arg name="userdao" ref="userdao"></constructor-arg>中name屬性值是相應set方法名的去掉set後的首字母小寫,ref是引入引入資料型別,即表示著物件屬性的注入
<bean id="userdao" class="com.sht.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.sht.service.impl.UserServiceImpl">
<constructor-arg name="userdao" ref="userdao"></constructor-arg>
</bean>
方式二:set方法
介面不變,改變一下UserServiceImpl 類,需要注意的是,setUserdao()的許可權是public,不能寫成private哦
public class UserServiceImpl implements UserService {
private UserDao userdao;
//許可權是public
public void setUserdao(UserDao userdao){
this.userdao = userdao;
}
@Override
public void save() {
userdao.save();
}
}
編寫xml配置檔案的bean,class屬性我就不再說明了。重點講解的是<property name="userdao" ref="userdao"></property>;name屬性值是相應set方法名的去掉set後的首字母小寫,ref是引入引入資料型別,即表示著物件屬性的注入;這裡把UserDaoImpl類的物件注入到UserServiceImpl類中,就可以呼叫其save()方法了
<bean id="userdao" class="com.sht.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.sht.service.impl.UserServiceImpl">
<property name="userdao" ref="userdao"></property>
</bean>
測試程式碼:
public void test5(){
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) context.getBean("userService");
userService.save();
}
執行結果:
此外,set方法中有一個特殊的方法:P名稱空間注入。其本質也是set方法注入,但比起上述的set方法注入更加方便,主要體現在配置檔案中,如下:
引入xmlns:p="http://www.springframework.org/schema/p"名稱空間,其次p:userdao-ref屬性值是跟ref對應的屬性值的含義是一樣的,這種方法可以作為了解
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userdao" class="com.sht.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.sht.service.impl.UserServiceImpl" p:userdao-ref="userdao"></bean>
</beans>
3、Bean的依賴注入資料型別
普通資料型別的注入
我用set方法的方式,講解bean的依賴注入。繼續在UserDaoImpl類中新增兩個基本資料型別和它們的set方法
private String name;
private Integer age;
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
public void show() {
System.out.println("名字是" + name + "的年齡是" + age);
}
修改xml配置檔案的bean,name的屬性值代表著set方法的名,value的屬性值表示你想要填入的屬性值
<bean id="userDao" class="com.sht.dao.impl.UserDaoImpl">
<property name="name" value="捲心菜"></property>
<property name="age" value="20"></property>
</bean>
寫一個測試類:
public void test7(){
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
UserDaoImpl contextBean = context.getBean(UserDaoImpl.class);
contextBean.show();
}
執行結果:
集合資料型別的注入
List<String>型別的注入
繼續在UserDaoImpl類中改動程式碼:
private List<String> stringList;
public void setStringList(List<String> stringList) {
this.stringList = stringList;
}
public void showStringList() {
System.out.println(stringList);
}
修改xml配置檔案,注入基本資料型別就是兩個關鍵字<list>和<value>
<bean id="userDao" class="com.sht.dao.impl.UserDaoImpl">
<property name="stringList">
<list>
<value>111</value>
<value>222</value>
<value>333</value>
</list>
</property>
</bean>
執行結果:
List<User>型別的注入
先建立一個User類,有對應的get和set方法,還有toString方法,方便測試使用
public class User {
private Integer id;
private String username;
private String password;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
修改xml配置檔案的bean,可以看出,與之前不同的是,<list>中用的是<ref>標籤,這個標籤表示的是注入引用資料型別
<bean id="user01" class="com.sht.domain.User">
<property name="id" value="1"></property>
<property name="username" value="捲心菜"></property>
<property name="password" value="123456"></property>
</bean>
<bean id="user02" class="com.sht.domain.User"></bean>
<bean id="userDao" class="com.sht.dao.impl.UserDaoImpl">
<property name="userList">
<list>
<ref bean="user01"></ref>
<ref bean="user02"></ref>
</list>
</property>
</bean>
執行結果:
Map<String,User> 型別的注入
繼續在UserDaoImpl類中改動程式碼:
private Map<String, User> stringUserMap;
public void setStringUserMap(Map<String, User> stringUserMap) {
this.stringUserMap = stringUserMap;
}
public void showStringUserMap() {
System.out.println(stringUserMap);
}
修改xml配置檔案,與之前不同的是,當使用的是map時,標籤用的是<map>和標籤<entry>,使用方法跟list標籤差不多
<bean id="user01" class="com.sht.domain.User">
<property name="id" value="1"></property>
<property name="username" value="捲心菜"></property>
<property name="password" value="123456"></property>
</bean>
<bean id="userDao" class="com.sht.dao.impl.UserDaoImpl">
<property name="stringUserMap">
<map>
<entry key="key1" value-ref="user01"></entry>
</map>
</property>
</bean>
執行結果:
需要注意的是,我們在選擇key屬性時,會有一個如圖所示的key-ref的提示,這代表著我們要用的key是一個引入資料型別,因為我用的key是String,所以選擇key
當使用value-ref時,也會出現value的值,其用法跟上面一樣
Properties型別的注入
繼續在UserDaoImpl類中改動程式碼:
private Properties properties;
public void setProperties(Properties properties) {
this.properties = properties;
}
public void showProperties(){
System.out.println(properties);
}
修改xml配置檔案,與之前的不同之處就是標籤使用的是<props>和標籤<prop>,使用的方法也是跟上面的方法類似
<bean id="userDao" class="com.sht.dao.impl.UserDaoImpl">
<property name="properties">
<props>
<prop key="key01">value1</prop>
<prop key="key02">value2</prop>
</props>
</property>
</bean>
執行結果:
4、引入其他配置檔案(分模組開發)
建立一個新的配置檔案applicationContext1.xml,實際開發中,Spring的配置內容非常多,這就導致Spring配置很繁雜且體積很大,所以,可以將部分配置拆解到其他配置檔案中,而在Spring主配置檔案通過import標籤進行載入
把applicationContext1.xml配置檔案中的配置內容引入到applicationContext.xml的實現方式:
<import resource="applicationContext1.xml"></import>
總結
以上就是Spring配置檔案的相關知識點,帶大家來看看Spring的重點配置:
- 程式碼重構,真的只有複雜化一條路嗎?
- 解讀分散式排程平臺Airflow在華為雲MRS中的實踐
- 透過例項demo帶你認識gRPC
- 帶你聚焦GaussDB(DWS)儲存時遊標使用
- 傳統到敏捷的轉型中,誰更適合做Scrum Master?
- 輕鬆解決研發知識管理難題
- Java中觀察者模式與委託,還在傻傻分不清
- 如何使用Python實現影象融合及加法運算?
- 什麼是強化學習?
- 探索開源工作流引擎Azkaban在MRS中的實踐
- GaussDB(DWS) NOT IN優化技術解密:排他分析場景400倍效能提升
- Java中觀察者模式與委託,還在傻傻分不清
- Java中的執行緒到底有哪些安全策略
- 一圖詳解java-class類檔案原理
- Java中的執行緒到底有哪些安全策略
- 擺平各類目標檢測識別AI應用,有它就夠了!
- KeyDB重量釋出6.3.0開源版,華為深度參與貢獻
- 如何使用Tomcat實現WebSocket即時通訊服務服務端
- GaussDB(for Influx)與開源企業版效能對比
- 一文詳述DMS資源池佇列阻塞告警及原理