spring Bean裝配的幾種方式簡單介紹


Spring容器負責創建應用程序中的bean同時通過ID來協調這些對象之間的關系。作為開發人員,我們需要告訴Spring要創建哪些bean並且如何將其裝配到一起。

spring中bean裝配有兩種方式

  • 隱式的bean發現機制和自動裝配
  • 在java代碼或者XML中進行顯示配置

當然這些方式也可以配合使用。

我們測試代碼如下

CompactDisc和MediaPlayer是兩個接口 其中MediaPlayer的構造方法參數類型為CompactDisc。
我們主要測試CompactDisc和MediaPlayer的實現有沒有注入進來,同時MediaPlayer接口對於CompactDisc的依賴有沒有滿足
package com.zcs;

import com.zcs.service.CompactDisc;
import com.zcs.service.MediaPlayer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertNotNull;

@RunWith(SpringJUnit4ClassRunner.class)
//XML配置
//@ContextConfiguration(locations ="spring-config.xml")
//Java代碼配置
@ContextConfiguration(classes =CDPlayerConfig.class)
public class CDPlayerTest {
    @Autowired
    private CompactDisc cd;
    @Autowired
    private MediaPlayer player;
    @Test
    public void cdShouldNotBeNull(){
        assertNotNull(cd);
    }
    @Test
    public void play(){
        assertEquals("Playing 哎呦不錯哦 by 周傑倫",player.play());
    }

}

 

1、自動化裝配

Spring從兩個角度來實現自動化裝配:

組件掃描(ComponentScan):自動發現應用上下文中所創建的bean

自動裝配(Autowired):自動滿足bean之間的依賴

CompactDisc接口類和實現類:

public interface CompactDisc {
    String play();
}
@Component
public class SgtPeppers implements CompactDisc { private String title="哎呦不錯哦"; private String artist="周傑倫"; @Override public String play() { return "Playing "+title+" by "+artist; } }

MediaPalyer接口類和實現類

public interface MediaPlayer {
    String play();
}
@Component
public class CDPlayer implements MediaPlayer {
    private CompactDisc cd ;
    @Autowired
    public CDPlayer(CompactDisc cd){
        this.cd=cd;
    }
    @Override
    public String play(){
      return cd.play();
    }
}

 

配置類CDPlayerConfig:

@Configuration
@ComponentScan
public class CDPlayerConfig {

}

 

@ComponentScan作用是掃描帶有@Component注解的類,並為其創建bean。默認是掃描同一包下的類,當然也可以加入參數,指定包名。

如@ComponentScan(basePackages={"com.zcs"})或者@ComponentScan(basePackageClasses={CDPlayer.class,DVDPlayer.class})(即這些類所在的包)

@Autowired滿足自動依賴裝配,可以作用在任何方法上面。

XML形式的自動裝配則修改測試類@ContextConfiguration,改成加載spring-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">
    <bean id="compactDisc" class="com.zcs.impl.SgtPeppers"></bean>
    <bean id="cdPlayer" class="com.zcs.impl.CDPlayer">
        <constructor-arg ref="compactDisc"></constructor-arg>
    </bean>
    <context:component-scan base-package="com.zcs">
</beans>

 2、顯示bean裝配

當想要將第三方庫中的組件裝配到你的應用中,在這種情況下是沒有辦法在它的類上面添加@Component和@Autowired注解的,因此就不能使用自動化裝配的方案。

 只能選擇java代碼或者xml顯示配置

首先可以把兩個實現類上的@Component,還有配置類中的@ComponentScan,CDPlayer類中方法上的@Autowired注解去掉。

這個時候測試應該都通不過。

Java代碼方式:修改CDPlayerConfig配置類為:

@Configuration
public class CDPlayerConfig {
    @Bean
    public CompactDisc sgtPeppers(){
        return new SgtPeppers();
    }
    @Bean
    public MediaPlayer getCDPlayer(){
        return new CDPlayer(sgtPeppers());
    }
   //@Bean
    //public MediaPlayer getCDPlayer(CompactDisc compactDisc){ // return new CDPlayer(compactDisc); //}
}

 

 再運行測試應該會通過了,解釋下 @Bean注解告訴Spring這個方法將會返回一個對象,該對象要注冊為Spring應用上下文中的bean。方法體中包含了最終生成bean實列的邏輯。

 第二個方法故意寫的奇怪一點,看起來CompactDisc是通過調用sgtPeppers()方法得到的,但並非如此,Spring會攔截對sgtPeppers方法的調用,轉而從上下文中直接獲取該方法所創建的bean,而不是每次都對其進行實際的調用。

比如:再添加一個方法(測試會通不過)

   @Bean
    public MediaPlayer anotherCDPlayer() {
        return new CDPlayer(sgtPeppers());
    }

 

這兩個方法依賴注入的CompactDisc將會是同一個bean。

當然通過情況下用注釋的方法更容易理解一點。

XML方式

首先CDPlayerTest為XML方式,同時修改spring-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">
    <bean id="compactDisc" class="com.zcs.impl.SgtPeppers"></bean>
    <bean id="cdPlayer" class="com.zcs.impl.CDPlayer">
        <constructor-arg ref="compactDisc"></constructor-arg>
    </bean>
    <context:component-scan base-package="com.zcs"/>
</beans>

 

組件掃描方式的配置不去掉也是沒影響的。

補充:

復雜一點的構造方法

修改SgtPeppers的構造方法

public class SgtPeppers implements CompactDisc {
    private String title="哎呦不錯哦";
    private String artist="周傑倫";
    private List<String> tracks=new ArrayList<>();

    public SgtPeppers(String title, String artist, List<String> tracks) {
        this.title = title;
        this.artist = artist;
        this.tracks = tracks;
    }

    @Override
    public String play() {
        return "Playing "+title+" by "+artist;
    }
}

 

同時修改spring-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">
    <bean id="compactDisc" class="com.zcs.impl.SgtPeppers">
        <constructor-arg index="0" value="雪狼湖"/>
        <constructor-arg index="1" value="張學友"/>
        <constructor-arg index="2">
            <list>
                <value>不老的傳說</value>
                <value>愛是永恆</value>
            </list>
        </constructor-arg>
    </bean>
    <bean id="cdPlayer" class="com.zcs.impl.CDPlayer">
        <constructor-arg ref="compactDisc"></constructor-arg>
    </bean>
    <context:component-scan base-package="com.zcs"/>
</beans>

 

還有屬性注入<property>,c和p命名空間使用就不細說了。對於xml的配置一般在java代碼中也會有對應的配置。但顯示配置用java代碼會類型安全一點

 

 參考:spring實戰第4版


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM