經過前文的學習,我們已經知道怎樣基于XML和Java進行顯式配置,與此同時,我們也驚人地發現顯式配置格外麻煩,我們必須寫好組態檔,把需要創建哪些Bean的資訊一個不差地填進組態檔里,這樣,Spring應用背景關系才能讀取組態檔創建Bean,若是需要創建的Bean不多,只有十個,二十個還好;若是需要創建的Bean很多,有一千個,兩千個,甚至更多,這時,把這些Bean的創建資訊一個不差地填進組態檔里就難免繁雜了,
那么,有沒有什么辦法能夠解決這個問題,讓事情優雅起來,簡單起來呢?
當然有的,比如,基于注解的自動配置就能優雅地解決這個問題,讓事情變得簡單,至于基于注解的自動配置有多自動,從而能夠簡化配置;不妨讓我們緊接前文實作的music-player,看看改用基于注解的自動配置能使配置簡化多少,進而學習基于注解的自動配置的基礎知識,為此,請打開music-player專案,修改AppConfig配置類如下:
1 package com.dream; 2 3 import org.springframework.context.annotation.*; 4 5 @Configuration 6 @ComponentScan(basePackages="com.dream") 7 public class AppConfig { 8 }
瞧,那些關于如何創建Bean的配置方法一個不剩,全沒了!卻見類上除了@Configuration注解之外,還帶有一個神秘的@ComponentScan注解,
這是怎么回事呢?
原來,基于注解的自動配置對配置類沒那么多要求,只要加上@ComponentScan注解就夠了,至于那些關于如何創建Bean的配置方法,基于注解的自動配置是一個也不需要的,于是問題來了,@ComponentScan到底是什么樣的注解?為什么它的功能如此強大,簡簡單單一句注解就能搞定配置?
其實,@ComponentScan注解只是啟用了組件掃描,別的事情一件也沒做,因此,@ComponentScan注解有個常用的basePackages屬性,用于指定需要掃描的包,需要掃描的包可以同時指定多個,不同的包之間用逗號隔開就行,Spring應用背景關系加載配置類之后如果發現配置類帶有@ComponentScan注解,就會掃描組件,掃描組件之前會先看一下basePackages屬性的值,如果basePackages屬性無值就掃描配置類所在的包;如果basePackages屬性有值就掃描該值指定的包,
于是我們知道了,AppConfig配置類上的@ComponentScan(basePackages="com.dream")注解只是啟用了組件掃描,告訴Spring應用背景關系掃描com.dream包,找出包里的所有組件,重點在于,找出所有組件之后呢?Spring應用背景關系能否自動創建和裝配Bean?如果Spring應用背景關系真能自動創建和裝配Bean,又是依據什么進行的呢?還有,組件是什么?帶著這些問題,讓我們修改一下Music類和Player類,如下:
Music類:
1 package com.dream; 2 3 import org.springframework.beans.factory.annotation.*; 4 import org.springframework.stereotype.*; 5 6 @Component(value = "https://www.cnblogs.com/evanlin/archive/2021/10/24/music") 7 public class Music { 8 private String musicName = null; 9 10 public String getMusicName() { 11 return this.musicName; 12 } 13 14 @Value(value="https://www.cnblogs.com/evanlin/archive/2021/10/24/執著") 15 public void setMusicName(String musicName) { 16 this.musicName = musicName; 17 } 18 }
Player類:
1 package com.dream; 2 3 import org.springframework.beans.factory.annotation.*; 4 import org.springframework.stereotype.*; 5 6 @Component(value = "https://www.cnblogs.com/evanlin/archive/2021/10/24/player") 7 public class Player { 8 private Music music = null; 9 10 public Music getMusic() { 11 return this.music; 12 } 13 14 @Autowired(required = true) 15 public void setMusic(Music music) { 16 this.music = music; 17 } 18 19 public void play() { 20 var musicName = this.music.getMusicName(); 21 var musicMessage = String.format("開始播放音樂《%s》", musicName); 22 System.out.println(musicMessage); 23 } 24 25 public void pause() { 26 var musicName = this.music.getMusicName(); 27 var musicMessage = String.format("暫停播放音樂《%s》", musicName); 28 System.out.println(musicMessage); 29 } 30 }
可以看到,Music類和Player類帶有這些注解:
1.Music類帶有@Component注解,
2.Music類的setMusicName方法帶有@Value("執著")注解,
3.Player類帶有@Component注解,
4.Player類的setMusic方法帶有@Autowired(required = true)注解,
這是怎么回事呢?
原來,Spring應用背景關系加載配置類之后如果發現類上帶有@ComponentScan注解,就會掃描指定的包,找出包里所有帶有@Component注解的類,這些帶有@Component注解的類就是組件,之后,Spring應用背景關系通過反射技術呼叫類的默認建構式創建Bean,這些Bean的id默認是類名的第一個字母變成小寫之后的字串,當然,我們也可設定@Component注解的value屬性指定Bean的id,
于是我們知道了,組件掃描的目的是發現組件,創建Bean,那么,Bean的裝配又是怎么進行的呢?
這就涉及@Value注解和@Autowired注解了,眾所周知,Bean的裝配分為兩種:一種是字面量值裝配;一種是物件裝配,Spring應用背景關系掃描組件之后,如果發現組件的方法帶有@Value注解,就會進行字面量值的自動裝配,如果發現組件的方法帶有@Autowired注解,就會進行物件的自動裝配,看看帶有@Autowired注解的方法需要什么型別的Bean,再從Spring應用背景關系里找到這種型別的Bean自動裝配上去,
因此,@Value注解有個常用的value屬性,這個屬性是字串型別的,用于指定字面量值,這樣,Spring應用背景關系讀到@Value注解的value屬性之后,就能進行字面量的自動裝配了,@Autowired注解有個常用的required屬性,這個屬性是布爾型別的,用于指定物件的裝配是不是必須的,當required屬性的值等于TRUE時,物件的裝配是必須的,如果Spring應用背景關系找不到相應在的Bean進行裝配,就會拋出org.springframework.beans.factory.NoSuchBeanDefinitionException型別的例外;當required屬性的值等于FALSE時,物件的裝配不是必須的,如果Spring應用背景關系找不到相應的Bean進行裝配,則不進行裝配,required屬性的默認值是TRUE,
于是我們知道了,Music類和Player類之所以帶有@Component注解,是為了能被組件掃描發現,Music類的setMusicName方法之所以帶有@Value("執著")注解,是為了把“執著”這個字面量值裝配進去,Player類的setMusic方法之所以帶有@Autowired注解,是為了讓Spring應用背景關系找到型別為Music的物件之后裝配進去,
非常明顯,基于注解的自動配置分為兩步:第一步是組件掃描(Component Scanning),第二步是自動裝配(Auto Wiring),Spring應用背景關系加載配置類之后,發現配置類帶有@ComponentScan注解,于是啟用組件掃描從basePackages屬性指定的包里找到所有組件,應用反射技術呼叫類的默認建構式創建Bean,之后,Spring應用背景關系開始自動裝配,通過帶有@Value注解的方法進行字面量值的自動裝配;通過帶有@Autowired注解的方法進行物件的自動裝配,于是,基于注解的自動配置完成了,
同時我們也應看到,基于注解的自動配置是通過組態檔啟用組件掃描的,這個組態檔可以是Java配置類,自然也可以是XML組態檔,比如,就music-player這個專案而言,如果采用XML啟用組件掃描,則可修改app-config.xml組態檔如下:
<?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"> <context:component-scan base-package="com.dream" /> </beans>
正如大家所料,那些關于如何創建Bean的配置資訊一個不剩,全沒了!卻多了以下兩樣東西:
1.XML模式檔案http://www.springframework.org/schema/context/spring-context.xsd
2.XML元素<context:component-scan base-package="com.dream" />
spring-context.xsd模式檔案定義了哪些XML元素可以用來配置Spring應用背景關系,<context:component-scan base-package="com.dream" />正是spring-context.xsd模式檔案定義的一個元素,用于啟用組件掃描,其用法與@ComponentScan注解是一樣的,這里不再贅述,
于是我們知道了,Spring提供了兩種配置方式:一種是顯式配置;一種是自動配置,顯式配置是通過XML或Java顯式描述Bean的創建資訊,再由Spring應用背景關系根據具體的配置資訊進行Bean的創建和裝配,因此,顯式配置分為兩種:一種是基于XML的顯式配置,通常也叫通過XML進行配置;一種是基于Java的顯式配置,通常也叫通過Java進行配置,自動配置由組件掃描和自動裝配兩部分組成,我們需用Java配置類或XML組態檔啟用組件掃描,再在類里添加注解,告訴Spring應用背景關系哪些類是組件以及Bean應該怎么裝配,這樣,Spring應用背景關系掃描組件之后就能進行Bean的創建和裝配了,因此,自動配置是一種基于注解的自動配置,通常也叫通過注解進行配置,
至此,關于配置的基礎知識介紹完了,想必大家還有很多困惑,比如關于自動裝配,當Spring應用背景關系里存在多個相同型別的物件時,Spring應用背景關系怎么知道應該選用哪個物件進行裝配呢?講清諸如這樣的問題需要花些篇幅,將在“細說Spring”的時候再行討論,現在,讓我們開啟新的征程,先來看看Spring是怎樣簡化JDBC的,
回傳目錄
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/335088.html
標籤:其他
