經過spring註解(@Component)來代表該類會做爲組件類,並告知Spring要爲這類建立bean,不過組件掃描默認是不啓動的,須要顯式的配置Spring,從而命令Spring去尋找帶有(@Component)註解的類,併爲其建立bean。java
一、定義接口spring
package com.seven.springTest.service; public interface HelloWorldApi { public void sayHello(); }
二、定義接口的實現類api
package com.seven.springTest.service.impl; import org.springframework.stereotype.Component; import com.seven.springTest.service.HelloWorldApi; @Component //經過註解指定該類組件類,告知spring要爲它建立Bean public class PersonHelloWorld implements HelloWorldApi { @Override public void sayHello() { System.out.println("Hello World,This Is Person!"); } }
三、前面說過了,spring並不能自動啓用組件掃描,須要進行顯式的配置,這裏經過java類來進行顯式的配置,定義java配置類HelloWorldConfig,在配置類中咱們沒有顯式的聲明任何bean,只不過是使用了@CompontentScan註解來啓用組件掃描數組
package com.seven.springTest; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan // 啓用組件掃描 public class HelloWorldConfig { }
如今全部的工做已經完成,咱們來測試下ide
package com.seven.springTest.main; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import com.seven.springTest.HelloWorldConfig; import com.seven.springTest.service.HelloWorldApi; public class HelloWorldTest { public static void main(String[] args) { //1. 聲明Spring上下文,採用java配置類 ApplicationContext ac = new AnnotationConfigApplicationContext(HelloWorldConfig.class); //2. 聲明Spring應用上下文,採用xml配置 //ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml"); //經過Spring上下文獲取Bean,在這裏Spring經過自動掃描發現了PersonHelloWorld的實現,並自動建立bean。 HelloWorldApi hwapi = ac.getBean(HelloWorldApi.class); //經過sayHello()的輸入內容能夠看到,hwapi爲PersonHelloWorld的實例 hwapi.sayHello(); } }
經過上的代碼,在控制檯會輸出下面的內容 「Hello World,This Is Person!」函數
Spring容器經過組件掃描發現了PersonHelloWorld類,併爲它建立了對應的bean。到此爲止,咱們經過簡單的註解實現自動化裝配,在上面的案例中,HelloWorldConfig配置類@ComponentSan若是沒有其餘配置,只會掃描HelloWorldConfig所在包或者它的子包,若是須要制定掃描的包,能夠經過工具
@ComponentScan("com.seven.springTest")
或者測試
@ComponentScan(basePackages="com.seven.springTest")
basePackages容許設置多個包,,只須要把basePackages熟悉設置成一個數組便可ui
@ComponentScan(basePackages={"com.seven.springTest.service","com.seven.springTest.impl"})
除了經過java配置類來設置Spring啓用組件掃描,還可能經過xml類顯式配置,參考下面xml配置,並在獲取Spring應用上下文時經過xml來初始化。this
<?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:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd"> <!-- 啓用Spring組件掃描--> <context:component-scan base-package="com.seven.springTest"></context:component-scan> </beans>
在上面的案例中,咱們經過@Component和@ComponentScan來隱式的配置完成了Bean的裝配工做,接下來咱們深刻的探討下@Component和@ComponentScan
Spring容器在管理Bean的時候,會給每個Bean有一個ID標識,上面的例子,若是HelloWorldApi的實現類有多個,那麼Spring容器該怎麼分配Bean呢,若是咱們在使用@Component的時候,沒有明確的給PersonHelloWorld設置一個ID,Spring容器會默認給bean給定一個ID,通常爲類名(第一個字母會變爲小寫,例如跑personHelloWorld),因此下面的代碼也是成立的
//經過bean的ID來獲取實例 HelloWorldApi hwapi = (HelloWorldApi) ac.getBean("personHelloWorld"); hwapi.sayHello();
同時咱們也能夠爲bean設置ID,以下:
@Component("person") //爲bean設置ID爲「person」 public class PersonHelloWorld implements HelloWorldApi { @Override public void sayHello() { // TODO Auto-generated method stub System.out.println("Hello World,This Is Person!"); } }
這樣咱們在獲取bean的時候就可經過ID來獲取,以下:
// 根據設置的bean ID來獲取bean HelloWorldApi hwapi = (HelloWorldApi) ac.getBean("person");
在以上的案例中咱們使用了@Component和@ComponentScan實現了組件掃描,目前爲止咱們都是對單一的對象進行操做,若是程序複雜點,對象之間存在依賴,該如何處理呢?下面咱們就來研究下如何爲bean添加註解實現自動裝配
在上面的案例中Person對整個世界說了一句Hello,可說話只有旁邊的人知道,咱們須要讓更多的聽到咱們的「hello world」,咱們就須要一些工具,咱們使用電視來廣播就能讓更多的人聽到了,首先咱們定義一個傳播工具接口
package com.seven.springTest.service; public interface TransmittingTool { void work(String message); }
接下來咱們來建立咱們的TV
package com.seven.springTest.service.impl; import org.springframework.stereotype.Component; import com.seven.springTest.service.TransmittingTool; @Component //設置爲須要被掃描到的組件 public class TVTool implements TransmittingTool { @Override public void work(String message) { //傳播工具工做,把咱們的消息傳播出去 System.out.println(message); } }
接下來咱們須要對咱們以前的PersonHelloWorld的sayHello()方法進行一些修改,讓它能夠經過傳播工具來對全世界說Hello
package com.seven.springTest.service.impl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.seven.springTest.service.HelloWorldApi; import com.seven.springTest.service.TransmittingTool; @Component public class PersonHelloWorld implements HelloWorldApi { //定義傳播工具 @Autowired //1.直接變量添加註解 private TransmittingTool transmittingTool; // @Autowired //2. 經過構造函數注入依賴 // public PersonHelloWorld(TransmittingTool transmittingTool) { // this.transmittingTool = transmittingTool; // } // @Autowired //3. 經過屬性的Setter方法注入依賴 // public void setTransmittingTool(TransmittingTool transmittingTool) { // this.transmittingTool = transmittingTool; // } // @Autowired //4. 經過其餘函數注入依賴 // public void inserttool(TransmittingTool transmittingTool){ // this.transmittingTool=transmittingTool; // } @Override public void sayHello() { // 經過傳播工具來sayHello transmittingTool.work("Hello World,This Is Person!--form TV"); } }
首先咱們定義了一個傳播工具,這個工具的具體實現咱們不清楚,須要Spring容器去給我注入依賴。
@Autowired直接可使用在類變量、構造函數、Setter和其餘任何方法上,參考代碼中1-4的實現
若是可以配置到1個知足要求的依賴,那麼這個被依賴的bean就會被裝配進來,若是沒有匹配的依賴bean,那麼應用上下文建立的時候,Spring會拋出一個異常,爲了不異常,咱們能夠把@Autowired的required設置爲false;
@Autowired(required=false) //2. 經過構造函數注入依賴 public PersonHelloWorld(TransmittingTool transmittingTool) { this.transmittingTool = transmittingTool; }
@Autowired的required設置給false後,Spring爲嘗試給bean自動裝配,注入依賴,若是沒有匹配的bean的話,Spring將會讓這個bean處於未裝配的狀態,當時把required設置爲false的時須要注意,由於這個依賴bean處於未裝配狀態,在調用依賴的時候,若是你的代碼作null的檢查,這個處於未裝配狀態的屬性有可能會發生異常。
若是有多個bean能知足依賴關係的話,Spring也會拋出異常,代表沒有明確指出選擇哪一個bean進行自動裝配。這個在後面我會單獨開一篇講解Spring的高級裝配,到時候在詳細說明,你們能夠關注後續的文章。