javascript
Spring学习(六)bean装配详解之 【通过注解装配 Bean】【基础配置方式】
本文借鑒:Spring學(xué)習(xí)(特此感謝!)
通過注解裝配 Bean
1、前言
優(yōu)勢
1.可以減少 XML 的配置,當(dāng)配置項多的時候,XML配置過多會導(dǎo)致項目臃腫難以維護
2.功能更加強大,既能實現(xiàn) XML 的功能,也提供了自動裝配的功能,采用了自動裝配后,程序猿所需要做的決斷就少了,更加有利于對程序的開發(fā),這就是“約定優(yōu)于配置”的開發(fā)原則
IOC發(fā)現(xiàn)Bean的兩種方式
組件掃描:通過定義資源的方式,讓 Spring IoC 容器掃描對應(yīng)的包,從而把 bean 裝配進來。
自動裝配:通過注解定義,使得一些依賴關(guān)系可以通過注解完成。
注解分為兩類
一類是使用Bean,即是把已經(jīng)在xml文件中配置好的Bean拿來用,完成屬性、方法的組裝;比如@Autowired , @Resource,可以通過byTYPE(@Autowired)、byNAME(@Resource)的方式獲取Bean;
一類是注冊Bean,@Component , @Repository , @ Controller , @Service , @Configration這些注解都是把你要實例化的對象轉(zhuǎn)化成一個Bean,放在IoC容器中,等你要用的時候,它會和上面的@Autowired , @Resource配合到一起,把對象、屬性、方法完美組裝。
2、使用@Compoent 裝配 Bean
我們把之前創(chuàng)建的 Student 類改一下:
package pojo;import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component;@Component(value = "student1") public class Student {@Value("1")int id;@Value("student_name_1")String name;// getter and setter }?解釋一下:
@Component注解:
表示 Spring IoC 會把這個類掃描成一個 bean 實例,而其中的 value 屬性代表這個類在 Spring 中的 id,這就相當(dāng)于在 XML 中定義的 Bean 的 id:<bean id="student1" class="pojo.Student" />,也可以簡寫成 @Component("student1"),甚至直接寫成 @Component ,對于不寫的,Spring IoC 容器就默認以類名來命名作為 id,只不過首字母小寫,配置到容器中。
@Value注解:
表示值的注入,跟在 XML 中寫 value 屬性是一樣的。
這樣我們就聲明好了我們要創(chuàng)建的一個 Bean,就像在 XML 中寫下了這樣一句話:
<bean name="student1" class="pojo.Student"><property name="id" value="1" /><property name="name" value="student_name_1"/> </bean>? 但是現(xiàn)在我們聲明了這個類,并不能進行任何的測試,因為 Spring IoC 并不知道這個 Bean 的存在,這個時候我們可以使用一個 StudentConfig 類去告訴 Spring IoC :
package pojo; import org.springframework.context.annotation.ComponentScan;@ComponentScan public class StudentConfig { }這個類十分簡單,沒有任何邏輯,但是需要說明兩點:
1、該類和 Student 類位于同一包名下
2、@ComponentScan注解:
代表進行掃描,默認是掃描當(dāng)前包的路徑,掃描所有帶有 @Component 注解的 POJO。
PS:也可以用XML來配置掃描路徑,不過推薦使用注解的形式
?
這樣一來,我們就可以通過 Spring 定義好的 Spring IoC 容器的實現(xiàn)類——AnnotationConfigApplicationContext 去生成 IoC 容器了:
ApplicationContext context = new AnnotationConfigApplicationContext(StudentConfig.class); Student student = (Student) context.getBean("student1", Student.class); student.printInformation();這里可以看到使用了 AnnotationConfigApplicationContext 類去初始化 Spring IoC 容器,它的配置項是 StudentConfig 類,這樣 Spring IoC 就會根據(jù)注解的配置去解析對應(yīng)的資源,來生成 IoC 容器了。
明顯的弊端:
- 對于 @ComponentScan 注解,它只是掃描所在包的 Java 類,但是更多的時候我們希望的是可以掃描我們指定的類
- 上面的例子只是注入了一些簡單的值,測試發(fā)現(xiàn),通過 @Value 注解并不能注入對象
@Component 注解存在著兩個配置項:
basePackages:它是由 base 和 package 兩個單詞組成的,而 package 還是用了復(fù)數(shù),意味著它可以配置一個 Java 包的數(shù)組,Spring 會根據(jù)它的配置掃描對應(yīng)的包和子包,將配置好的 Bean 裝配進來
basePackageClasses:它由 base、package 和 class 三個單詞組成,采用復(fù)數(shù),意味著它可以配置多個類, Spring 會根據(jù)配置的類所在的包,為包和子包進行掃描裝配對應(yīng)配置的 Bean
我們來試著重構(gòu)之前寫的 StudentConfig 類來驗證上面兩個配置項:
package pojo; import org.springframework.context.annotation.ComponentScan;@ComponentScan(basePackages = "pojo")//配置掃描pojo包 public class StudentConfig { }// —————————————————— 【 宇宙超級無敵分割線】—————————————————— package pojo;import org.springframework.context.annotation.ComponentScan;@ComponentScan(basePackageClasses = pojo.Student.class)//配置掃描pojo包下名為Student的類 public class StudentConfig { }對于 【basePackages】 和 【basePackageClasses】 的選擇問題:
【basePackages】 的可讀性會更好一些,所以在項目中會優(yōu)先選擇使用它,但是在需要大量重構(gòu)的工程中,盡量不要使用【basePackages】,因為很多時候重構(gòu)修改包名需要反復(fù)地配置,而 IDE 不會給你任何的提示,而采用【basePackageClasses】會有錯誤提示。
3、自動裝配——@Autowired
定義:由 Spring 自己發(fā)現(xiàn)對應(yīng)的 Bean,自動完成裝配工作的方式(根據(jù)類型查找)
例子解析:
1.先在 Package【service】下創(chuàng)建一個 StudentService 接口:
package service;public interface StudentService {public void printStudentInfo(); }PS:使用接口是 Spring 推薦的方式,這樣可以更為靈活,可以將定義和實現(xiàn)分離
2.為上面的接口創(chuàng)建一個 StudentServiceImp 實現(xiàn)類:
@Component("studentService")//表示IoC把這個類掃描成一個bean實例(這里簡寫了,括號內(nèi)等同于XML配置方式時的id) public class StudentServiceImp implements StudentService {@Autowired//Spring自己發(fā)現(xiàn)bean并裝配private Student student = null;public void printStudentInfo() {System.out.println("學(xué)生的 id 為:" + student.getName());System.out.println("學(xué)生的 name 為:" + student.getName());} }3.編寫測試類:
// 第一步:修改 StudentConfig 類,告訴 Spring IoC 在哪里去掃描它: package pojo;import org.springframework.context.annotation.ComponentScan;@ComponentScan(basePackages = {"pojo", "service"}) public class StudentConfig { }// 或者也可以在 XML 文件中聲明去哪里做掃描 <context:component-scan base-package="pojo" /> <context:component-scan base-package="service" />// 第二步:編寫測試類: package test;import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import pojo.StudentConfig; import service.StudentService; import service.StudentServiceImp;public class TestSpring {public static void main(String[] args) {// 通過注解的方式初始化 Spring IoC 容器ApplicationContext context = new AnnotationConfigApplicationContext(StudentConfig.class);StudentService studentService = context.getBean("studentService", StudentServiceImp.class);studentService.printStudentInfo();} }小結(jié):
@Autowired 注解表示在 Spring IoC 定位所有的 Bean 后,再根據(jù)類型尋找資源,然后將其注入。
過程:定義 Bean ——》 初始化 Bean(掃描) ——》 根據(jù)屬性需要從 Spring IoC 容器中搜尋滿足要求的 Bean ——》 滿足要求則注入
問題: IoC 容器可能會尋找失敗,此時會拋出異常(默認情況下,Spring IoC 容器會認為一定要找到對應(yīng)的 Bean 來注入到這個字段,但有些時候并不是一定需要,比如日志)
解決: 通過配置項 required 來改變,比如 @Autowired(required = false),該屬性可控制IOC容器找不到Bean時不報錯。
PS:@Autowired 注解不僅僅能配置在屬性之上,還允許方法配置,常見的 Bean 的 setter 方法也可以使用它來完成注入,總之一切需要 Spring IoC 去尋找 Bean 資源的地方都可以用到
轉(zhuǎn)載于:https://www.cnblogs.com/riches/p/11521428.html
總結(jié)
以上是生活随笔為你收集整理的Spring学习(六)bean装配详解之 【通过注解装配 Bean】【基础配置方式】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java8 時間API
- 下一篇: 元组字典集合内置方法与拷贝