Spring配置
1. 別名
alias 設定別名 , 為bean設定別名 , 可以設定多個別名
<!--設定別名:在獲取Bean的時候可以使用別名獲取--> <alias name="userT" alias="userNew"/>
2. Bean的配置
<!--bean就是java物件,由Spring創建和管理-->
<!--
id 是bean的識別符號,要唯一,如果沒有配置id,name就是默認識別符號
如果配置id,又配置了name,那么name是別名
name可以設定多個別名,可以用逗號,分號,空格隔開
如果不配置id和name,可以根據applicationContext.getBean(.class)獲取物件;
class是bean的全限定名=包名+類名
-->
<bean id="hello" name="hello2 h2,h3;h4" >
<property name="name" value="https://www.cnblogs.com/wyh518/archive/2023/02/16/Spring"/>
</bean>
3. import
團隊的合作通過import來實作 .
<import resource="{path}/beans.xml"/>
依賴注入(DI)
- 依賴注入(Dependency Injection,DI),
- 依賴 : 指Bean物件的創建依賴于容器 . Bean物件的依萊澩 .
- 注入 : 指Bean物件所依賴的資源 , 由容器來設定和裝配 .
1 構造器注入
在上一篇博客已經詳細講過了
2 set注入 (重點)
要求被注入的屬性 , 必須有set方法 , set方法的方法名由set + 屬性首字母大寫 , 如果屬性是boolean型別 , 沒有set方法 , 是 is .
測驗pojo類 :
Address.java
public class Address {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
Student.java
package com.hang.pojo;
import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set;
public class Student { private String name; private Address address; private String[] books; private List<String> hobbys; private Map<String,String> card; private Set<String> games; private String wife; private Properties info;
public void setName(String name) { this.name = name; }
public void setAddress(Address address) { this.address = address; }
public void setBooks(String[] books) { this.books = books; }
public void setHobbys(List<String> hobbys) { this.hobbys = hobbys; }
public void setCard(Map<String, String> card) { this.card = card; }
public void setGames(Set<String> games) { this.games = games; }
public void setWife(String wife) { this.wife = wife; }
public void setInfo(Properties info) { this.info = info; }
public void show(){ System.out.println("name="+ name + ",address="+ address.getAddress() + ",books=" ); for (String book:books){ System.out.print("<<"+book+">>\t"); } System.out.println("\n愛好:"+hobbys); System.out.println("card:"+card); System.out.println("games:"+games); System.out.println("wife:"+wife); System.out.println("info:"+info); } }
2、1 常量注入
<bean id="student" >
<property name="name" value="https://www.cnblogs.com/wyh518/archive/2023/02/16/小明"/>
</bean>
測驗:
@Test
public void test01(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Student student = (Student) context.getBean("student");
System.out.println(student.getName());
}
2、2 Bean注入
注意點:這里的值是一個參考,ref
<bean id="addr" > <property name="address" value="https://www.cnblogs.com/wyh518/archive/2023/02/16/重慶"/> </bean>
<bean id="student" > <property name="name" value="https://www.cnblogs.com/wyh518/archive/2023/02/16/小明"/> <property name="address" ref="addr"/> </bean>
2、3 陣列注入
<bean id="student" > <property name="name" value="https://www.cnblogs.com/wyh518/archive/2023/02/16/小明"/> <property name="address" ref="addr"/> <property name="books"> <array> <value>西游記</value> <value>紅樓夢</value> <value>水滸傳</value> </array> </property> </bean>
2、4 List注入
<property name="hobbys"> <list> <value>聽歌</value> <value>看電影</value> <value>爬山</value> </list> </property>
2、5 Map注入
<property name="card"> <map> <entry key="中國郵政" value="https://www.cnblogs.com/wyh518/archive/2023/02/16/456456456465456"/> <entry key="建設" value="https://www.cnblogs.com/wyh518/archive/2023/02/16/1456682255511"/> </map> </property>
2、6 set注入
<property name="games"> <set> <value>LOL</value> <value>BOB</value> <value>COC</value> </set> </property>
2、7 Null注入
<property name="wife"><null/></property>
2、8 Properties注入
<property name="info"> <props> <prop key="學號">20190604</prop> <prop key="性別">男</prop> <prop key="姓名">小明</prop> </props> </property>
測驗結果:

3 拓展注入實作
User.java : 【注意:這里沒有有參構造器!】
public class User {
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
1、P命名空間注入 : 需要在頭檔案中假如約束檔案
匯入約束 : xmlns:p="http://www.springframework.org/schema/p" <!--P(屬性: properties)命名空間 , 屬性依然要設定set方法--> <bean id="user" p:name="腹白" p:age="18"/>
2、c 命名空間注入 : 需要在頭檔案中假如約束檔案
匯入約束 : xmlns:c="http://www.springframework.org/schema/c" <!--C(構造: Constructor)命名空間 , 屬性依然要設定set方法--> <bean id="user" c:name="腹白" c:age="18"/>
發現問題:爆紅了,剛才我們沒有寫有參構造!
解決:把有參構造器加上,這里也能知道,c 就是所謂的構造器注入!
測驗代碼:
@Test
public void test02(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) context.getBean("user");
System.out.println(user);
}
4 Bean的作用域
在Spring中,那些組成應用程式的主體及由Spring IoC容器所管理的物件,被稱之為bean,簡單地講, bean就是由IoC容器初始化、裝配及管理的物件 .

幾種作用域中,request、session作用域僅在基于web的應用中使用(不必關心你所采用的是什么web 應用框架),只能用在基于web的Spring ApplicationContext環境,
4.1 Singleton
當一個bean的作用域為Singleton,那么Spring IoC容器中只會存在一個共享的bean實體,并且所有對 bean的請求,只要id與該bean定義相匹配,則只會回傳bean的同一實體,Singleton是單例型別,就是 在創建起容器時就同時自動創建了一個bean的物件,不管你是否使用,他都存在了,每次獲取到的物件 都是同一個物件,注意,Singleton作用域是Spring中的預設作用域,要在XML中將bean定義成 singleton,可以這樣配置:
<bean id="ServiceImpl" scope="singleton">
測驗:
@Test
public void test03(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) context.getBean("user");
User user2 = (User) context.getBean("user");
System.out.println(user==user2);
}
4.2 Prototype
當一個bean的作用域為Prototype,表示一個bean定義對應多個物件實體,Prototype作用域的bean會 導致在每次對該bean請求(將其注入到另一個bean中,或者以程式的方式呼叫容器的getBean()方法) 時都會創建一個新的bean實體,Prototype是原型型別,它在我們創建容器的時候并沒有實體化,而是 當我們獲取bean的時候才會去創建一個物件,而且我們每次獲取到的物件都不是同一個物件,根據經 驗,對有狀態的bean應該使用prototype作用域,而對無狀態的bean則應該使用singleton作用域,在 XML中將bean定義成prototype,可以這樣配置:
<bean id="account" scope="prototype"/> 或者 <bean id="account" singleton="false"/>
4.3 Request
當一個bean的作用域為Request,表示在一次HTTP請求中,一個bean定義對應一個實體;即每個HTTP 請求都會有各自的bean實體,它們依據某個bean定義創建而成,該作用域僅在基于web的Spring ApplicationContext情形下有效,考慮下面bean定義:
<bean id="loginAction" class=cn.csdn.LoginAction" scope="request"/>
針對每次HTTP請求,Spring容器會根據loginAction bean的定義創建一個全新的LoginAction bean實 例,且該loginAction bean實體僅在當前HTTP request內有效,因此可以根據需要放心的更改所建實體 的內部狀態,而其他請求中根據loginAction bean定義創建的實體,將不會看到這些特定于某個請求的 狀態變化,當處理請求結束,request作用域的bean實體將被銷毀,
4.4 Session
當一個bean的作用域為Session,表示在一個HTTP Session中,一個bean定義對應一個實體,該作用域 僅在基于web的Spring ApplicationContext情形下有效,考慮下面bean定義:
<bean id="userPreferences" scope="session"/>
針對某個HTTP Session,Spring容器會根據userPreferences bean定義創建一個全新的 userPreferences bean實體,且該userPreferences bean僅在當前HTTP Session內有效,與request作 用域一樣,可以根據需要放心的更改所創建實體的內部狀態,而別的HTTP Session中根據 userPreferences創建的實體,將不會看到這些特定于某個HTTP Session的狀態變化,當HTTP Session 最終被廢棄的時候,在該HTTP Session作用域內的bean也會被廢棄掉,
Bean的自動裝配
- 自動裝配是使用spring滿足bean依賴的一種方法
- spring會在應用背景關系中為某個bean尋找其依賴的bean,
Spring中bean有三種裝配機制,分別是:
- 在xml中顯式配置;
- 在java中顯式配置;
- 隱式的bean發現機制和自動裝配,
這里我們主要講第三種:自動化的裝配bean,
Spring的自動裝配需要從兩個角度來實作,或者說是兩個操作:
- 組件掃描(component scanning):spring會自動發現應用背景關系中所創建的bean;
- 自動裝配(autowiring):spring自動滿足bean之間的依賴,也就是我們說的IoC/DI;
組件掃描和自動裝配組合發揮巨大威力,使的顯示的配置降低到最少,
推薦不使用自動裝配xml配置 , 而使用注解 .
1、測驗環境搭建
1. 新建一個專案
2. 新建兩個物體類,Cat Dog 都有一個叫的方法
public class Cat {
public void shout() {
System.out.println("miao~");
}
}
public class Dog {
public void shout() {
System.out.println("wang~");
}
}
3. 新建一個用戶類 User
public class User {
private Cat cat;
private Dog dog;
private String str;
}
4. 撰寫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="dog" class="com.kuang.pojo.Dog"/> <bean id="cat" class="com.kuang.pojo.Cat"/>
<bean id="user" class="com.kuang.pojo.User"> <property name="cat" ref="cat"/> <property name="dog" ref="dog"/> <property name="str" value="qinjiang"/> </bean> </beans>
5. 測驗
public class MyTest {
@Test
public void testMethodAutowire() {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User user = (User) context.getBean("user");
user.getCat().shout();
user.getDog().shout();
}
}
結果正常輸出,環境OK
2、byName
autowire byName (按名稱自動裝配)
由于在手動配置xml程序中,常常發生字母缺漏和大小寫等錯誤,而無法對其進行檢查,使得開發效率 降低,
采用自動裝配將避免這些錯誤,并且使配置簡單化,
測驗:
1. 修改bean配置,增加一個屬性 autowire="byName"
<bean id="user" autowire="byName">
<property name="str" value="https://www.cnblogs.com/wyh518/archive/2023/02/16/qinjiang"/>
</bean>
2. 再次測驗,結果依舊成功輸出!
3. 我們將 cat 的bean id修改為 catXXX
4. 再次測驗, 執行時報空指標java.lang.NullPointerException,因為按byName規則找不對應set方 法,真正的setCat就沒執行,物件就沒有初始化,所以呼叫時就會報空指標錯誤,
小結:
當一個bean節點帶有 autowire byName的屬性時,
- 將查找其類中所有的set方法名,例如setCat,獲得將set去掉并且首字母小寫的字串,即cat,
- 去spring容器中尋找是否有此字串名稱id的物件,
- 如果有,就取出注入;如果沒有,就報空指標例外,
3、byType
autowire byType (按型別自動裝配)
使用autowire byType首先需要保證:同一型別的物件,在spring容器中唯一,如果不唯一,會報不唯一 的例外,
NoUniqueBeanDefinitionException
測驗:
1. 將user的bean配置修改一下 : autowire="byType"
2. 測驗,正常輸出
3. 在注冊一個cat 的bean物件!
<bean id="dog" /> <bean id="cat" /> <bean id="cat2" />
<bean id="user" autowire="byType"> <property name="str" value="https://www.cnblogs.com/wyh518/archive/2023/02/16/qinjiang"/> </bean>
4. 測驗,報錯:NoUniqueBeanDefinitionException
5. 刪掉cat2,將cat的bean名稱改掉!測驗!因為是按型別裝配,所以并不會報例外,也不影響最后 的結果,甚至將id屬性去掉,也不影響結果,
這就是按照型別自動裝配!
4 使用注解
jdk1.5開始支持注解,spring2.5開始全面支持注解,
準備作業: 利用注解的方式注入屬性,
1. 在spring組態檔中引入context檔案頭
xmlns:context="http://www.springframework.org/schema/context" http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
2. 開啟屬性注解支持!
<context:annotation-config/>
4.1、@Autowired
- @Autowired是按型別自動轉配的,不支持id匹配,
- 需要匯入 spring-aop的包!
測驗:
1. 將User類中的set方法去掉,使用@Autowired注解
public class User {
@Autowired
private Cat cat;
@Autowired
private Dog dog;
private String str;
public Cat getCat() {
return cat;
}
public Dog getDog() {
return dog;
}
public String getStr() {
return str;
}
}
2. 此時組態檔內容
<context:annotation-config/>
<bean id="dog" /> <bean id="cat" /> <bean id="user" />
3. 測驗,成功輸出結果!
【科普】
@Autowired(required=false) 說明: false,物件可以為null;true,物件必須存物件,不能為null,
//如果允許物件為null,設定required = false,默認為true @Autowired(required = false) private Cat cat;
4.2、@Qualifier
- @Autowired是根據型別自動裝配的,加上@Qualifier則可以根據byName的方式自動裝配
- @Qualifier不能單獨使用,
測驗實驗步驟:
1. 組態檔修改內容,保證型別存在物件,且名字不為類的默認名字!
<bean id="dog1" /> <bean id="dog2" /> <bean id="cat1" /> <bean id="cat2" />
2. 沒有加Qualifier測驗,直接報錯
3. 在屬性上添加Qualifier注解
@Autowired @Qualifier(value = "https://www.cnblogs.com/wyh518/archive/2023/02/16/cat2") private Cat cat; @Autowired @Qualifier(value = "https://www.cnblogs.com/wyh518/archive/2023/02/16/dog2") private Dog dog;
4. 測驗,成功輸出!
4.3、@Resource
- @Resource如有指定的name屬性,先按該屬性進行byName方式查找裝配;
- 其次再進行默認的byName方式進行裝配;
- 如果以上都不成功,則按byType的方式自動裝配,
- 都不成功,則報例外,
物體類:
public class User {
//如果允許物件為null,設定required = false,默認為true
@Resource(name = "cat2")
private Cat cat;
@Resource
private Dog dog;
private String str;
}
beans.xml
<bean id="dog" /> <bean id="cat1" /> <bean id="cat2" /> <bean id="user" />
測驗:結果OK
組態檔2:beans.xml , 刪掉cat2
<bean id="dog" /> <bean id="cat1" />
物體類上只保留注解
@Resource private Cat cat; @Resource private Dog dog;
結果:OK
結論:先進行byName查找,失敗;再進行byType查找,成功,
5、小結
@Autowired與@Resource異同:
- @Autowired與@Resource都可以用來裝配bean,都可以寫在欄位上,或寫在setter方法上,
- @Autowired默認按型別裝配(屬于spring規范),默認情況下必須要求依賴物件必須存在,如果 要允許null 值,可以設定它的required屬性為false,如:@Autowired(required=false) ,如果我 們想使用名稱裝配可以結合@Qualifier注解進行使用
- @Resource(屬于J2EE復返),默認按照名稱進行裝配,名稱可以通過name屬性進行指定,如果 沒有指定name屬性,當注解寫在欄位上時,默認取欄位名進行按照名稱查找,如果注解寫在 setter方法上默認取屬性名進行裝配, 當找不到與名稱匹配的bean時才按照型別進行裝配,但是 需要注意的是,如果name屬性一旦指定,就只會按照名稱進行裝配,
它們的作用相同都是用注解方式注入物件,但執行順序不同,@Autowired先byType,@Resource先 byName,
使用注解開發
1、說明
在spring4之后,想要使用注解形式,必須得要引入aop的包

在組態檔當中,還得要引入一個context約束
<?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: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">
</beans>
2、Bean的實作
我們之前都是使用 bean 的標簽進行bean注入,但是實際開發中,我們一般都會使用注解!
1. 配置掃描哪些包下的注解
<!--指定注解掃描包--> <context:component-scan base-package="com.hang.pojo"/>
2. 在指定包下撰寫類,增加注解
@Component("user")
// 相當于組態檔中 <bean id="user" />
public class User {
public String name = "腹白";
}
3. 測驗
@Test
public void test(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
User user = (User) applicationContext.getBean("user");
System.out.println(user.name);
}
3、屬性注入
使用注解注入屬性
1. 可以不用提供set方法,直接在直接名上添加@value("值")
@Component("user")
// 相當于組態檔中 <bean id="user" />
public class User {
@Value("秦疆")
// 相當于組態檔中 <property name="name" value="https://www.cnblogs.com/wyh518/archive/2023/02/16/秦疆"/>
public String name;
}
2. 如果提供了set方法,在set方法上添加@value("值");
@Component("user")
public class User {
public String name;
@Value("秦疆")
public void setName(String name) {
this.name = name;
}
}
4、衍生注解
我們這些注解,就是替代了在組態檔當中配置步驟而已!更加的方便快捷!
@Component三個衍生注解
為了更好的進行分層,Spring可以使用其它三個注解,功能一樣,目前使用哪一個功能都一樣,
- @Controller:web層
- @Service:service層
- @Repository:dao層
寫上這些注解,就相當于將這個類交給Spring管理裝配了!
5、自動裝配注解
在Bean的自動裝配已經講過了,可以回顧!
6、作用域
@scope
- singleton:默認的,Spring會采用單例模式創建這個物件,關閉工廠 ,所有的物件都會銷毀,
- prototype:多例模式,關閉工廠 ,所有的物件不會銷毀,內部的垃圾回識訓制會回收
@Controller("user")
@Scope("prototype")
public class User {
@Value("秦疆")
public String name;
}
7、小結
XML與注解比較
- XML可以適用任何場景 ,結構清晰,維護方便
- 注解不是自己提供的類使用不了,開發簡單方便
xml與注解整合開發 :推薦最佳實踐
- xml管理Bean
- 注解完成屬性注入
- 使用程序中, 可以不用掃描,掃描是為了類上的注解
<context:annotation-config/>
作用:
- 進行注解驅動注冊,從而使注解生效
- 用于激活那些已經在spring容器里注冊過的bean上面的注解,也就是顯示的向Spring注冊
- 如果不掃描包,就需要手動配置bean
- 如果不加注解驅動,則注入的值為null!
8、基于Java類進行配置
JavaConfig 原來是 Spring 的一個子專案,它通過 Java 類的方式提供 Bean 的定義資訊,在 Spring4 的 版本, JavaConfig 已正式成為 Spring4 的核心功能 ,
測驗:
1. 撰寫一個物體類,Dog
@Component //將這個類標注為Spring的一個組件,放到容器中!
public class Dog {
public String name = "dog";
}
2. 新建一個config配置包,撰寫一個MyConfig配置類
@Configuration //代表這是一個配置類
public class MyConfig {
@Bean //通過方法注冊一個bean,這里的回傳值就Bean的型別,方法名就是bean的id!
public Dog dog(){
return new Dog();
}
}
3. 測驗
@Test
public void test2(){
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
Dog dog = (Dog) applicationContext.getBean("dog");
System.out.println(dog.name);
}
4. 成功輸出結果!
匯入其他配置如何做呢?
1. 我們再撰寫一個配置類!
@Configuration //代表這是一個配置類
public class MyConfig2 {
}
2. 在之前的配置類中我們來選擇匯入這個配置類
@Configuration
@Import(MyConfig2.class) //匯入合并其他配置類,類似于組態檔中的 inculde 標簽
public class MyConfig {
@Bean
public Dog dog(){
return new Dog();
}
}
關于這種Java類的配置方式,我們在之后的SpringBoot 和 SpringCloud中還會大量看到,我們需要知道 這些注解的作用即可!
本文來自博客園,作者:腹白,轉載請注明原文鏈接:https://www.cnblogs.com/wyh518/
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/544090.html
標籤:其他
