Spring學習系列(三) 經過Java代碼裝配Bean

上面梳理了經過註解來隱式的完成了組件的掃描和自動裝配,下面來學習下如何經過顯式的配置的裝配beanjava

2、經過Java類裝配bean

在前面定義了HelloWorldConfig類,並使用@ComponentScan和@Configuration註解,@Configuration註解代表了這個類是一個java配置類,該類用在獲取Spring應用上下文時,告訴Spring建立bean的細節,經過@ComponentScan,咱們啓用了Spring的自動組件掃描,如今就讓咱們來看若是經過java類來顯式的配置bean,下面咱們經過一個音樂播放器的案例來實踐一下。spring

咱們播放音樂,首先須要一個播放器,而後須要音樂資源,首先咱們定義一個播放器接口和音樂資源接口ide

package com.seven.springTest.service;

// 播放器
public interface MediaPlayer {  
    void play();
}
package com.seven.springTest.service;

// 音樂資源
public interface MusicSource {

    void play();
}

本次播放音樂咱們是光驅來播放cd音樂,下面咱們來實現上面的接口,函數

package com.seven.springTest.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.seven.springTest.service.MusicSource;
import com.seven.springTest.service.MediaPlayer;

//定義光驅播放器
public class CDPlayer implements MediaPlayer {
    
    @Autowired
    // 定義一個音樂資源,這裏經過@Autowired來聲明須要注入MusicSource的依賴
    private MusicSource cd ;

    @Override
    public void play() {
        //播放音樂
        cd.play();
    }
}

實現音樂資源爲光盤學習

package com.seven.springTest.service.impl;
import com.seven.springTest.service.MusicSource;

public class CDSource implements MusicSource {

    private String title = "七里香";
    private String artist = "周杰倫";

    @Override
    public void play() {
        System.out.println("Playing " + title + " by " + artist);
    }
}

到目前爲止咱們已經完成播放器、音樂資源的接口定義和具體的實現,那麼咱們若是告訴Spring應該建立哪麼bean,併爲它們注入什麼依賴呢?在第一部分,咱們經過@Component註解來隱式的告訴Spring,如今咱們經過java類來配置bean組件。測試

@Bean

@Bean註解告訴Spring函數將返回一個對象,該對象須要註冊爲Spring應用上下文中的bean,該方法中包含了產生bean實例的邏輯code

package com.seven.springTest.Configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import com.seven.springTest.service.MusicSource;
import com.seven.springTest.service.MediaPlayer;
import com.seven.springTest.service.impl.CDPlayer;
import com.seven.springTest.service.impl.CDSource;

@Configuration
public class MediePlayerConfig {
    
    @Bean   //該方法返回的MusicSource對象須要註冊爲Spring應用上下文中的bean
    public MusicSource cdsource(){
        return new CDSource();
    }
    
    @Bean  //該方法返回的MediaPlayer對象須要註冊爲Spring應用上下文中的bean
    public MediaPlayer cdplayer(){
        return new CDPlayer();
    }
    
}

MediePlayerConfig類中,咱們只添加了@Configuration註解,以前的@ComponentScan註解移除了,沒有配置啓動Spring的組件掃描,另外接口的實現類也沒有添加@Component註解,咱們經過@Bean註解來告訴Spring哪些對象須要被註冊爲Spring應用上下文中的bean。cdsource()方法返回了一個MusicSource類型的實例對象CDSource,該對象被註冊到Spring應用上下文,一樣的cdplayer()方法返回了一個MediaPlayer類型的實例CDPlayer註冊到Spring應用上下文中。下面咱們來測試下xml

package com.seven.springTest.main;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.seven.springTest.Configuration.MediePlayerConfig;
import com.seven.springTest.Configuration.HelloWorldConfig;
import com.seven.springTest.service.MediaPlayer;

public class MediaPlayerTest {
    public static void main(String[] args) {
        //加載java配置類獲取Spring應用上下文
        ApplicationContext ac = new AnnotationConfigApplicationContext(MediePlayerConfig.class);
        //獲取播放器
        MediaPlayer player= ac.getBean(MediaPlayer.class);
        //播放
        player.play();
    }
}

咱們在獲取播放器bean的時候,其實獲取到的就是MediePlayerConfig類中cdplayer()返回的對象CDPlayer,在CDPlayer中咱們依賴MusicSource,經過@Autowired註解,Spring自動爲該bean注入了對MusicSource的依賴,因此在測試代碼中咱們只是獲取了MediaPlayer對象的實例player,至於player有哪些依賴,咱們都不知道,都是由Spring容器來給我注入,這裏只關心播放器player,這就是Spring給咱們帶來的便捷,咱們不須要用代碼去管理對象的依賴關係,對象全部依賴的資源都有Spring容器來爲咱們注入。對象

隨着技術的發展,有一天光驅也能夠插入U盤播放MP3音樂了,這個時候咱們來實現一個MP3的音樂資源接口

package com.seven.springTest.service.impl;

import com.seven.springTest.service.MusicSource;

public class MP3Source implements MusicSource {
    
    private String title = "外婆";
    private String artist = "周杰倫";

    @Override
    public void play() {
        // TODO Auto-generated method stub
        System.out.println("MP3 Playing " + title + " by " + artist);
    }

}

在第一部分自動裝配中,若是Spring發現了多個bean知足依賴關係,Spring就沒法選擇了,那麼若是咱們定義了MP3Source的實現,如今會不會也出現這樣的狀況呢?經過運行程序,咱們發現沒有產生任何影響,CDPlayer bean被注入的MusicSource依賴仍是CDSource。這是由於咱們在MediePlayerConfig中經過cdsource()告知了Spring產生bean的實現邏輯,那咱們來修改下cdsource()

@Bean   //該方法返回的MusicSource對象須要註冊爲Spring應用上下文中的bean
public MusicSource cdsource(){
    //返回MP3Source實例
    return new MP3Source();
}

咱們再運行下測試方法,發現輸出內容變成了「==MP3 Playing 外婆 by 周杰倫==」,說明注入的依賴對象實現發生變化了,這是由於 cdsource()內實現的是返回MP3Source的實例。

同以前@Component同樣,添加@Bean註解的方法返回的bean也會被默認分配一個ID,默認狀況下和方法名相同,如cdsource()方法返回的bean的ID就爲「cdsource」,咱們也能夠指定bean的ID,以下:

@Bean(name="myCdplayer")      //該方法返回的MediaPlayer對象須要註冊爲Spring應用上下文中的bean
public MediaPlayer cdplayer(){
    return new CDPlayer();
}

這樣在獲取bean的時候就能夠經過ID來獲取

public class MediaPlayerTest {
    public static void main(String[] args) {
        //加載java配置類獲取Spring應用上下文
        ApplicationContext ac = new AnnotationConfigApplicationContext(MediePlayerConfig.class);
        //根據ID獲取bean
        MediaPlayer player= (MediaPlayer) ac.getBean("myCdplayer");
        //播放
        player.play();
    }
}

上面的案例中CDPlayer bean它依賴了MusicSource的依賴,咱們在CDPlayer類中經過@Autowired聲明瞭CDPlayer須要的依賴,這裏仍是一種經過註解隱式的配置,下面咱們來經過java配置類來實現。

若是是顯式的配置,因爲MediePlayerConfig中配置的bean都是經過方法返回的,因此須要在返回對象bean的方法裏注入依賴:

@Bean(name="myCdplayer")  //該方法返回的MediaPlayer對象須要註冊爲Spring應用上下文中的bean
public MediaPlayer cdplayer(){
    return new CDPlayer(cdsource());   //經過對象的構造函數注入依賴
}

或者

@Bean(name="myCdplayer")  //該方法返回的MediaPlayer對象須要註冊爲Spring應用上下文中的bean
public MediaPlayer cdplayer(MusicSource musicSource){
    return new CDPlayer(musicSource);   //經過對象的構造函數注入依賴
}

經過上面2中方式配置,Spring均可以對CDPlayer中的MusicSource對象完成依賴注入,下面咱們在定義一個bean配置

@Bean(name="myCdplayer")  //該方法返回的MediaPlayer對象須要註冊爲Spring應用上下文中的bean
public MediaPlayer cdplayer(){
    return new CDPlayer(cdsource());   //經過對象的構造函數注入依賴
}

@Bean(name="otherCdplayer")   //定義另一個bean對象,
public MediaPlayer othercdplayer(){
    return new CDPlayer(cdsource());
}

MediaPlayer接口增長一個獲取播放資源的方法

package com.seven.springTest.service;

public interface MediaPlayer {

    /**
    * 獲取播放器加載的資源 
    * @return MusicSource
    */
    MusicSource getResource();

    /**
     * 播放
     */
    void play();
}

解下列,咱們修改下Test代碼

package com.seven.springTest.main;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.seven.springTest.Configuration.MediePlayerConfig;
import com.seven.springTest.Configuration.HelloWorldConfig;
import com.seven.springTest.service.MediaPlayer;

public class MediaPlayerTest {
    public static void main(String[] args) {
        // 加載java配置類獲取Spring應用上下文
        ApplicationContext ac = new AnnotationConfigApplicationContext(MediePlayerConfig.class);
        // 獲取播放器
        MediaPlayer player = (MediaPlayer) ac.getBean("myCdplayer");
        MediaPlayer otherplayer = (MediaPlayer) ac.getBean("otherCdplayer");
        if (player.getResource().equals(otherplayer.getResource())) {
            System.out.println("true");
        }
        // 播放
        //player.play();
    }
}

運行後,咱們發現輸出「true」,這說明的什麼狀況呢,咱們在cdplayer()和othercdplayer()方法中在調用CDPlayer(cdsource())構造時,經過cdsource()獲取的音樂資源對象是相同的,在默認狀況下,Spring中的bean都是單例的,Spring會攔截對cdsource()的調用,並確保返回的是Spring建立的bean,也就是Spring自己在第一次調用cdsource()所建立的bean。


3、經過XML來裝配bean

相關文章
相關標籤/搜索