一文帶你了解Spring中存入Bean和獲取Bean的方式
0. Spring中的五大注解

上圖中就是五大類注解對應(yīng)的層,通過源碼可以看到其他四個(gè)注解都基于@Conponent
1. 存入 Bean
Spring既然是一個(gè)包含眾多工具方法的IoC容器,它是一個(gè)控制反轉(zhuǎn)的容器,所以就需要將Bean對象存入到容器中,需要用的時(shí)候從容器中獲取Bean對象,下面我們來介紹下存入Bean對象。
1.1 在 xml 中存入 Bean 對象
<?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è)要注入的對象取個(gè)名字, class就是 要存入的 Bean 的類型是哪一個(gè)
<bean id = "user" class="com.java.demo.User"></bean>
</beans>
1.2 通過配置 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">
<!-- 通過配置掃描路徑 -->
<content:component-scan base-package="com.java.demo"></content:component-scan>
</beans>配置了 Bean 的掃描路徑,只有當(dāng)前目錄下的類才會(huì)被掃描是否加了類注解,如果加了類注解后,就會(huì)將 所有加了類注解的類 存入到 IoC容器中。
@Component
public class User {
public void say(){
System.out.println("Hello User...");
}
}類注解存Bean需要注意幾點(diǎn)
- 如果類名為大駝峰命名規(guī)則,那么獲取 Bean 的默認(rèn)名稱,就是 類名首字母小寫
- 如果不滿足首字母大寫,第二個(gè)字母小寫,那么 Bean 的名稱,就是原類名,這點(diǎn)可以看源碼知道

1.3 通過配置 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">
<!-- 通過配置掃描路徑 -->
<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...");
}
}在上述代碼中,我們可以通過 在方法上 加上 @Bean 注解 將該方法存入到 IoC 容器中,并且可以直接獲取到該對象。

在使用 @Bean 注解的時(shí)候,需要注意幾點(diǎn)
- @Bean 注解必須配合 五大類注解一塊使用
- @Bean 注解的默認(rèn)命名 = 方法名稱
- 如果使用 @Bean(“xxxx”)方式,那么名稱就是 xxxx, 并且 @Bean({“xxx”,“xxxxx”,“xxxxxx”}),里面可以類似和數(shù)組一樣多個(gè)名稱
- 如果@Bean重命名后,那么默認(rèn)的方法名就沒用,獲取Bean的時(shí)候就不能寫默認(rèn)方法名
- 如果多個(gè) Bean 使用相同的名稱,則不會(huì)報(bào)錯(cuò),只會(huì)存儲(chǔ)第一個(gè) Bean對象,之后相同名稱的不會(huì)存入,會(huì)自動(dòng)忽略
2. 獲取 Bean
2.1 依賴查找(DF)
依賴查找(依賴Bean的名稱),有兩種方式,一種是 ApplicationContext, 一種是 BeanFactory。這兩種都是容器管理對象,都可以獲取到 Bean對象
2.1.1 ApplicationContext
public class App {
public static void main(String[] args) {
// 1. 獲取 Spring 上下文對象
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
// 2。獲取 Bean 對象
Student student = (Student) context.getBean("student");
System.out.println(student);
}
}2.1.2 BeanFactory
public static void main(String[] args) {
// 1. 得到 spring 上下文對象
BeanFactory context = new XmlBeanFactory(new ClassPathResource("spring-config.xml"));
// 2. 獲取 Bean 對象
//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的子類,其擁有更多功能(國際化支持、資源訪問支持、事件傳播) | BeanFactory是ApplicationContext的父類 |
| ApplicationContext加載Bean:一次性加載所有Bean對象 | BeanFactory加載Bean:懶加載,按需加載(使用一個(gè)加載一個(gè)) |

2.2 依賴注入(DI)
在 spring 中實(shí)現(xiàn)依賴注入的常見方式有3種:
- 1.屬性注入
- 2.setter注入
- 3.構(gòu)造方法注入
2.2.1 屬性注入
@Controller
public class UserController {
/**
* 屬性注入
*/
@Autowired
private UserService userService;
// 此處 main方法里面,必須使用依賴查找的方式,先獲取到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)簡單、使用簡單,只需要在屬性上加一個(gè)注解@Autowired,就不需要自己new一個(gè)對象,直接獲得注入的對象。
缺點(diǎn):
- 無法注入一個(gè)用 final 修飾的對象

- 因?yàn)樵贘ava語法中,final修飾的對象(不可變),要么一開始就賦值,要么在構(gòu)造方法里面賦值。而上述使用屬性注入,注入final修飾的對象,就不符合規(guī)范,所以不行。
- 只能適用于 IoC 容器:如果將這些代碼放到其他非IoC容器中,那么代碼就會(huì)失效
- 設(shè)計(jì)原則:更容易違背單一原則,因?yàn)閷傩宰⑷氡容^簡單,那么可能就會(huì)在一個(gè)類中注入多個(gè)對象,這就可能不符合程序的單一職責(zé)問題。
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):似乎沒什么優(yōu)點(diǎn),而且比屬性注入更加麻煩,要說唯一可能有用的就是,完全符合單一職責(zé)設(shè)計(jì)原則,每個(gè) setter 只針對一個(gè)對象。Setter注入 也適用于非IoC容器
缺點(diǎn):
- 不能注入 final 對象

- 由于是 Setter 注入,提供了 set 方法,那么注入的對象可以隨時(shí)被更改
2.2.3 構(gòu)造方法注入(Spring4.x之后推薦的)
@Controller
public class UserController3 {
private final UserService userService;
/**
* 構(gòu)造方法注入
*/
// @Autowired 此處如果構(gòu)造方法參數(shù)只有一個(gè)的時(shí)候,該注解可有可無
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 修飾的對象

注入對象不會(huì)被更改,因?yàn)槭窃跇?gòu)造方法注入的,構(gòu)造方法在對象創(chuàng)建的時(shí)候只會(huì)創(chuàng)建一次
注入的對象會(huì)被完全初始化
通用性會(huì)更好,無論在 IoC容器 還是 非 IoC容器中都能用
缺點(diǎn):
- 寫法更加復(fù)雜
- 使用構(gòu)造方法,無法解決循環(huán)依賴的問題
Spring官方推薦的是構(gòu)造方法的注入,可以注入不可變對象,通用性更好;如果想要注入可變對象,那么可以使用 Setter 注入。
3. 解決同一類型多個(gè) Bean 的報(bào)錯(cuò)問題

上述代碼,可以看到報(bào)錯(cuò),出現(xiàn)了多個(gè)同一類型的多個(gè)Bean報(bào)錯(cuò),需要1個(gè),找到了2個(gè)。如何解決呢
- 1.@Autowired 配合 @Qualifier(value = “xxx”)一起使用,里面參數(shù)加方法名字

- 2.使用@Resource(name = “xxxx”)

4. @Resource 和 @Autowired
出身不同:@Resource來自于JDK,@Resource來自于Spring
支持參數(shù)不同:@Resource支持更多的參數(shù)

@Autowired只支持一個(gè)參數(shù)設(shè)置
使用上的區(qū)別:@Resource不支持構(gòu)造方法的注入

兼容性問題:@Autowired在社區(qū)版 IDEA可能會(huì)誤報(bào);
以上就是一文帶你了解Spring中存入Bean和獲取Bean的方式的詳細(xì)內(nèi)容,更多關(guān)于Spring存入和獲取Bean方式的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java異常鏈表throw結(jié)構(gòu)assert詳細(xì)解讀
這篇文章主要給大家介紹了關(guān)于Java中方法使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-08-08
SpringBoot項(xiàng)目打包發(fā)布到外部tomcat(出現(xiàn)各種異常的解決)
這篇文章主要介紹了SpringBoot項(xiàng)目打包發(fā)布到外部tomcat(出現(xiàn)各種異常的解決),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
Java實(shí)現(xiàn)身份證號碼驗(yàn)證源碼示例分享
本篇文章主要介紹了Java實(shí)現(xiàn)身份證號碼驗(yàn)證源碼示例分享,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-10-10
Spring boot actuator端點(diǎn)啟用和暴露操作
這篇文章主要介紹了Spring boot actuator端點(diǎn)啟用和暴露操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07
Java實(shí)現(xiàn)的校驗(yàn)銀行卡功能示例
這篇文章主要介紹了Java實(shí)現(xiàn)的校驗(yàn)銀行卡功能,結(jié)合完整實(shí)例形式分析了java針對銀行卡類型、歸屬地等信息的判斷、讀取相關(guān)操作技巧,需要的朋友可以參考下2018-06-06

