Spring學習系列(二) 自動化裝配Bean

1、Spring裝配-自動化裝配

@Component和@ComponentScan

經過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添加註解實現自動裝配

@AutoWired

在上面的案例中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. 直接在變量上添加註解
  2. 在構造函數上添加註解,在spring容器經過構造器實例化bean的時候,會傳入一個提供給transmittingTool的實例,注入依賴;
  3. 經過Setter方法或者其餘函數,Spring在初始化bean之後,會盡可能的去知足bean的全部依賴,若是使用第4個種注入,咱們在HelloWorldTest中重來沒有調用過inserttool()方法,但是sayHello()仍是能正常執行,Spring會去根據@Autowired來儘可能嘗試去注入PersonHelloWorld的依賴。

若是可以配置到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的高級裝配,到時候在詳細說明,你們能夠關注後續的文章。

相關文章
相關標籤/搜索