0. Spring中的五大注解
上圖中就是五大類注解對應(yīng)的層,通過源碼可以看到其他四個注解都基于@Conponent
1. 存入 Bean
Spring既然是一個包含眾多工具方法的IoC容器,它是一個控制反轉(zhuǎn)的容器,所以就需要將Bean對象存入到容器中,需要用的時候從容器中獲取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 就是給 這個要注入的對象取個名字, class就是 要存入的 Bean 的類型是哪一個
<bean id = "user" class="com.java.demo.User"></bean>
</beans>
1.2 通過配置 Bean 掃描路徑 + 類注解 實現(xiàn) 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">
<!-- 通過配置掃描路徑 -->
<content:component-scan base-package="com.java.demo"></content:component-scan>
</beans>
配置了 Bean 的掃描路徑,只有當(dāng)前目錄下的類才會被掃描是否加了類注解,如果加了類注解后,就會將 所有加了類注解的類 存入到 IoC 容器中。
@Component
public class User {
public void say(){
System.out.println("Hello User...");
}
}
類注解存Bean需要注意幾點
- 如果類名為大駝峰命名規(guī)則,那么獲取 Bean 的默認(rèn)名稱,就是 類名首字母小寫
- 如果不滿足首字母大寫,第二個字母小寫,那么 Bean 的名稱,就是原類名,這點可以看源碼知道
![]()
1.3 通過配置 Bean 掃描路徑 + 方法注解 實現(xiàn) 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">
<!-- 通過配置掃描路徑 -->
<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 getStudent(){
Student student = new Student();
student.setName("張三");
student.setAge(18);
return student;
}
public void say(){
System.out.println("Hello User...");
}
}
在上述代碼中,我們可以通過 在方法上 加上 @Bean 注解 將該方法存入到 IoC 容器中,并且可以直接獲取到該對象。
在使用 @Bean 注解的時候,需要注意幾點
- @Bean 注解必須配合 五大類注解一塊使用
- @Bean 注解的默認(rèn)命名 = 方法名稱
- 如果使用 @Bean(“xxxx”)方式,那么名稱就是 xxxx, 并且 @Bean({“xxx”,“xxxxx”,“xxxxxx”}),里面可以類似和數(shù)組一樣多個名稱
- 如果@Bean重命名后,那么默認(rèn)的方法名就沒用,獲取Bean的時候就不能寫默認(rèn)方法名
- 如果多個 Bean 使用相同的名稱,則不會報錯,只會存儲第一個 Bean對象,之后相同名稱的不會存入,會自動忽略
2. 獲取 Bean
2.1 依賴查找(DF)
依賴查找(依賴Bean的名稱),有兩種方式,一種是 ApplicationContext, 一種是 BeanFactory。這兩種都是容器管理對象,都可以獲取到 Bean對象
2.11 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.12 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.13 Application VS BeanFactory
ApplicationContext | BeanFactory |
---|---|
ApplicationContext是BeanFactory的子類,其擁有更多功能(國際化支持、資源訪問支持、事件傳播) | BeanFactory是ApplicationContext的父類 |
ApplicationContext加載Bean:一次性加載所有Bean對象 | BeanFactory加載Bean:懶加載,按需加載(使用一個加載一個) |
2.2 依賴注入(DI)
在 spring 中實現(xiàn)依賴注入的常見方式有3種:
- 1.屬性注入
- 2.setter注入
- 3.構(gòu)造方法注入
2.21 屬性注入
@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)點: 實現(xiàn)簡單、使用簡單,只需要在屬性上加一個注解@Autowired,就不需要自己new一個對象,直接獲得注入的對象。
缺點:
- 無法注入一個用 final 修飾的對象
因為在Java語法中,final修飾的對象(不可變),要么一開始就賦值,要么在構(gòu)造方法里面賦值。而上述使用屬性注入,注入final修飾的對象,就不符合規(guī)范,所以不行。
- 只能適用于 IoC 容器:如果將這些代碼放到其他非IoC容器中,那么代碼就會失效
- 設(shè)計原則:更容易違背單一原則,因為屬性注入比較簡單,那么可能就會在一個類中注入多個對象,這就可能不符合程序的單一職責(zé)問題。
2.22 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)點:似乎沒什么優(yōu)點,而且比屬性注入更加麻煩,要說唯一可能有用的就是,完全符合單一職責(zé)設(shè)計原則,每個 setter 只針對一個對象。Setter注入 也適用于非IoC容器
缺點:
- 不能注入 final 對象
- 由于是 Setter 注入,提供了 set 方法,那么注入的對象可以隨時被更改
2.23 構(gòu)造方法注入(Spring4.x之后推薦的)
@Controller
public class UserController3 {
private final UserService userService;
/**
* 構(gòu)造方法注入
*/
// @Autowired 此處如果構(gòu)造方法參數(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)點:
-
可以注入 被final 修飾的對象
-
注入對象不會被更改,因為是在構(gòu)造方法注入的,構(gòu)造方法在對象創(chuàng)建的時候只會創(chuàng)建一次
-
注入的對象會被完全初始化
-
通用性會更好,無論在 IoC容器 還是 非 IoC容器中都能用
缺點:
- 寫法更加復(fù)雜
- 使用構(gòu)造方法,無法解決循環(huán)依賴的問題
Spring官方推薦的是構(gòu)造方法的注入,可以注入不可變對象,通用性更好;如果想要注入可變對象,那么可以使用 Setter 注入。
3. 解決同一類型多個 Bean 的報錯問題
上述代碼,可以看到報錯,出現(xiàn)了多個同一類型的多個Bean報錯,需要1個,找到了2個。如何解決呢
- 1.@Autowired 配合 @Qualifier(value = “xxx”)一起使用,里面參數(shù)加方法名字
- 2.使用@Resource(name = “xxxx”)
3. @Resource 和 @Autowired
-
出身不同:@Resource來自于JDK,@Resource來自于Spring
-
支持參數(shù)不同:@Resource支持更多的參數(shù)
@Autowired只支持一個參數(shù)設(shè)置 -
使用上的區(qū)別:@Resource不支持構(gòu)造方法的注入
文章來源:http://www.zghlxwxcb.cn/news/detail-595250.html
-
兼容性問題:@Autowired在社區(qū)版 IDEA可能會誤報;文章來源地址http://www.zghlxwxcb.cn/news/detail-595250.html
到了這里,關(guān)于一文帶你了解Spring中存入Bean和獲取Bean的方式的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!