一文帶你了解Spring中存入Bean和獲取Bean的方式
0. Spring中的五大注解
上圖中就是五大類(lèi)注解對(duì)應(yīng)的層,通過(guò)源碼可以看到其他四個(gè)注解都基于@Conponent
1. 存入 Bean
Spring既然是一個(gè)包含眾多工具方法的IoC容器,它是一個(gè)控制反轉(zhuǎn)的容器,所以就需要將Bean對(duì)象存入到容器中,需要用的時(shí)候從容器中獲取Bean對(duì)象,下面我們來(lái)介紹下存入Bean對(duì)象。
1.1 在 xml 中存入 Bean 對(duì)象
<?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:content="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 https://www.springframework.org/schema/context/spring-context.xsd"> // 這句代碼中, id 就是給 這個(gè)要注入的對(duì)象取個(gè)名字, class就是 要存入的 Bean 的類(lèi)型是哪一個(gè) <bean id = "user" class="com.java.demo.User"></bean> </beans>
1.2 通過(guò)配置 Bean 掃描路徑 + 類(lèi)注解 實(shí)現(xiàn) Bean 的存儲(chǔ)
<?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:content="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 https://www.springframework.org/schema/context/spring-context.xsd"> <!-- 通過(guò)配置掃描路徑 --> <content:component-scan base-package="com.java.demo"></content:component-scan> </beans>
配置了 Bean 的掃描路徑,只有當(dāng)前目錄下的類(lèi)才會(huì)被掃描是否加了類(lèi)注解,如果加了類(lèi)注解后,就會(huì)將 所有加了類(lèi)注解的類(lèi) 存入到 IoC容器中。
@Component public class User { public void say(){ System.out.println("Hello User..."); } }
類(lèi)注解存Bean需要注意幾點(diǎn)
- 如果類(lèi)名為大駝峰命名規(guī)則,那么獲取 Bean 的默認(rèn)名稱(chēng),就是 類(lèi)名首字母小寫(xiě)
- 如果不滿(mǎn)足首字母大寫(xiě),第二個(gè)字母小寫(xiě),那么 Bean 的名稱(chēng),就是原類(lèi)名,這點(diǎn)可以看源碼知道
1.3 通過(guò)配置 Bean 掃描路徑 + 方法注解 實(shí)現(xiàn) Bean 的存儲(chǔ)
<?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:content="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 https://www.springframework.org/schema/context/spring-context.xsd"> <!-- 通過(guò)配置掃描路徑 --> <content:component-scan base-package="com.java.demo"></content:component-scan> </beans>
public class Student { private String name; private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
@Component public class User { @Bean public Student student(){ Student student = new Student(); student.setName("張三"); student.setAge(18); return student; } public void say(){ System.out.println("Hello User..."); } }
在上述代碼中,我們可以通過(guò) 在方法上 加上 @Bean 注解 將該方法存入到 IoC 容器中,并且可以直接獲取到該對(duì)象。
在使用 @Bean 注解的時(shí)候,需要注意幾點(diǎn)
- @Bean 注解必須配合 五大類(lèi)注解一塊使用
- @Bean 注解的默認(rèn)命名 = 方法名稱(chēng)
- 如果使用 @Bean(“xxxx”)方式,那么名稱(chēng)就是 xxxx, 并且 @Bean({“xxx”,“xxxxx”,“xxxxxx”}),里面可以類(lèi)似和數(shù)組一樣多個(gè)名稱(chēng)
- 如果@Bean重命名后,那么默認(rèn)的方法名就沒(méi)用,獲取Bean的時(shí)候就不能寫(xiě)默認(rèn)方法名
- 如果多個(gè) Bean 使用相同的名稱(chēng),則不會(huì)報(bào)錯(cuò),只會(huì)存儲(chǔ)第一個(gè) Bean對(duì)象,之后相同名稱(chēng)的不會(huì)存入,會(huì)自動(dòng)忽略
2. 獲取 Bean
2.1 依賴(lài)查找(DF)
依賴(lài)查找(依賴(lài)Bean的名稱(chēng)),有兩種方式,一種是 ApplicationContext, 一種是 BeanFactory。這兩種都是容器管理對(duì)象,都可以獲取到 Bean對(duì)象
2.1.1 ApplicationContext
public class App { public static void main(String[] args) { // 1. 獲取 Spring 上下文對(duì)象 ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml"); // 2。獲取 Bean 對(duì)象 Student student = (Student) context.getBean("student"); System.out.println(student); } }
2.1.2 BeanFactory
public static void main(String[] args) { // 1. 得到 spring 上下文對(duì)象 BeanFactory context = new XmlBeanFactory(new ClassPathResource("spring-config.xml")); // 2. 獲取 Bean 對(duì)象 //Student student = (Student)context.getBean("user"); Student student = (Student)context.getBean("student"); System.out.println(student.toString()); }
2.1.3 Application VS BeanFactory
ApplicationContext | BeanFactory |
---|---|
ApplicationContext是BeanFactory的子類(lèi),其擁有更多功能(國(guó)際化支持、資源訪(fǎng)問(wèn)支持、事件傳播) | BeanFactory是ApplicationContext的父類(lèi) |
ApplicationContext加載Bean:一次性加載所有Bean對(duì)象 | BeanFactory加載Bean:懶加載,按需加載(使用一個(gè)加載一個(gè)) |
2.2 依賴(lài)注入(DI)
在 spring 中實(shí)現(xiàn)依賴(lài)注入的常見(jiàn)方式有3種:
- 1.屬性注入
- 2.setter注入
- 3.構(gòu)造方法注入
2.2.1 屬性注入
@Controller public class UserController { /** * 屬性注入 */ @Autowired private UserService userService; // 此處 main方法里面,必須使用依賴(lài)查找的方式,先獲取到UserController public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml"); UserController userController = (UserController) context.getBean("userController"); userController.userService.say(); } }
屬性注入:
優(yōu)點(diǎn): 實(shí)現(xiàn)簡(jiǎn)單、使用簡(jiǎn)單,只需要在屬性上加一個(gè)注解@Autowired,就不需要自己new一個(gè)對(duì)象,直接獲得注入的對(duì)象。
缺點(diǎn):
- 無(wú)法注入一個(gè)用 final 修飾的對(duì)象
- 因?yàn)樵贘ava語(yǔ)法中,final修飾的對(duì)象(不可變),要么一開(kāi)始就賦值,要么在構(gòu)造方法里面賦值。而上述使用屬性注入,注入final修飾的對(duì)象,就不符合規(guī)范,所以不行。
- 只能適用于 IoC 容器:如果將這些代碼放到其他非IoC容器中,那么代碼就會(huì)失效
- 設(shè)計(jì)原則:更容易違背單一原則,因?yàn)閷傩宰⑷氡容^簡(jiǎn)單,那么可能就會(huì)在一個(gè)類(lèi)中注入多個(gè)對(duì)象,這就可能不符合程序的單一職責(zé)問(wèn)題。
2.2.2 Setter注入
@Controller public class UserController2 { private UserService userService; /** * setter注入 */ @Autowired public void setUserService(UserService userService) { this.userService = userService; } public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml"); UserController2 userController2 = (UserController2) context.getBean("userController2"); userController2.userService.say(); } }
優(yōu)點(diǎn):似乎沒(méi)什么優(yōu)點(diǎn),而且比屬性注入更加麻煩,要說(shuō)唯一可能有用的就是,完全符合單一職責(zé)設(shè)計(jì)原則,每個(gè) setter 只針對(duì)一個(gè)對(duì)象。Setter注入 也適用于非IoC容器
缺點(diǎn):
- 不能注入 final 對(duì)象
- 由于是 Setter 注入,提供了 set 方法,那么注入的對(duì)象可以隨時(shí)被更改
2.2.3 構(gòu)造方法注入(Spring4.x之后推薦的)
@Controller public class UserController3 { private final UserService userService; /** * 構(gòu)造方法注入 */ // @Autowired 此處如果構(gòu)造方法參數(shù)只有一個(gè)的時(shí)候,該注解可有可無(wú) public UserController3(UserService userService) { this.userService = userService; } public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml"); UserController3 userController3 = (UserController3) context.getBean("userController3"); userController3.userService.say(); } }
優(yōu)點(diǎn):
- 可以注入 被final 修飾的對(duì)象
注入對(duì)象不會(huì)被更改,因?yàn)槭窃跇?gòu)造方法注入的,構(gòu)造方法在對(duì)象創(chuàng)建的時(shí)候只會(huì)創(chuàng)建一次
注入的對(duì)象會(huì)被完全初始化
通用性會(huì)更好,無(wú)論在 IoC容器 還是 非 IoC容器中都能用
缺點(diǎn):
- 寫(xiě)法更加復(fù)雜
- 使用構(gòu)造方法,無(wú)法解決循環(huán)依賴(lài)的問(wèn)題
Spring官方推薦的是構(gòu)造方法的注入,可以注入不可變對(duì)象,通用性更好;如果想要注入可變對(duì)象,那么可以使用 Setter 注入。
3. 解決同一類(lèi)型多個(gè) Bean 的報(bào)錯(cuò)問(wèn)題
上述代碼,可以看到報(bào)錯(cuò),出現(xiàn)了多個(gè)同一類(lèi)型的多個(gè)Bean報(bào)錯(cuò),需要1個(gè),找到了2個(gè)。如何解決呢
- 1.@Autowired 配合 @Qualifier(value = “xxx”)一起使用,里面參數(shù)加方法名字
- 2.使用@Resource(name = “xxxx”)
4. @Resource 和 @Autowired
出身不同:@Resource來(lái)自于JDK,@Resource來(lái)自于Spring
支持參數(shù)不同:@Resource支持更多的參數(shù)
@Autowired只支持一個(gè)參數(shù)設(shè)置
使用上的區(qū)別:@Resource不支持構(gòu)造方法的注入
兼容性問(wèn)題:@Autowired在社區(qū)版 IDEA可能會(huì)誤報(bào);
以上就是一文帶你了解Spring中存入Bean和獲取Bean的方式的詳細(xì)內(nèi)容,更多關(guān)于Spring存入和獲取Bean方式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java異常鏈表throw結(jié)構(gòu)assert詳細(xì)解讀
這篇文章主要給大家介紹了關(guān)于Java中方法使用的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-08-08SpringBoot項(xiàng)目打包發(fā)布到外部tomcat(出現(xiàn)各種異常的解決)
這篇文章主要介紹了SpringBoot項(xiàng)目打包發(fā)布到外部tomcat(出現(xiàn)各種異常的解決),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09一文帶你了解Spring的Bean初始化過(guò)程和生命周期
Spring的核心功能有三點(diǎn)IOC、DI、AOP,IOC則是基礎(chǔ),也是Spring功能的最核心的點(diǎn)之一。今天一起來(lái)總結(jié)下Spring中Bean是怎么被創(chuàng)建出來(lái)的2023-03-03Java實(shí)現(xiàn)身份證號(hào)碼驗(yàn)證源碼示例分享
本篇文章主要介紹了Java實(shí)現(xiàn)身份證號(hào)碼驗(yàn)證源碼示例分享,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10Idea中maven無(wú)法下載依賴(lài)包問(wèn)題解決
用過(guò)idea開(kāi)發(fā)過(guò)項(xiàng)目的同學(xué),偶爾會(huì)遇到項(xiàng)目中有一些依賴(lài)沒(méi)法下載,或者依賴(lài)包已經(jīng)有項(xiàng)目卻無(wú)法掃到的問(wèn)題,本文就詳細(xì)的介紹了解決方法,感興趣的可以了解一下2020-08-08Spring boot actuator端點(diǎn)啟用和暴露操作
這篇文章主要介紹了Spring boot actuator端點(diǎn)啟用和暴露操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07詳解SpringBoot同時(shí)可以處理多少請(qǐng)求
在日常操作中,相信很多人在SpringBoot能同時(shí)處理多少請(qǐng)求問(wèn)題上存在疑惑,本文就來(lái)詳細(xì)的介紹一下,感興趣的可以了解一下2024-06-06Java實(shí)現(xiàn)的校驗(yàn)銀行卡功能示例
這篇文章主要介紹了Java實(shí)現(xiàn)的校驗(yàn)銀行卡功能,結(jié)合完整實(shí)例形式分析了java針對(duì)銀行卡類(lèi)型、歸屬地等信息的判斷、讀取相關(guān)操作技巧,需要的朋友可以參考下2018-06-06Java設(shè)計(jì)模式之訪(fǎng)問(wèn)者模式
這篇文章介紹了Java設(shè)計(jì)模式之訪(fǎng)問(wèn)者模式,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-10-10