【Spring】Spring的bean裝配

前言

beanSpring最基礎最核心的部分,Spring簡化代碼主要是依賴於bean,下面學習Spring中如何裝配beanjava

裝配bean

Spring在裝配bean時很是靈活,其提供了三種方式裝配beannode

  • XML中進行顯式配置。
  • Java中進行顯式配置。
  • 隱式的bean發現機制和自動裝配。

自動化裝配bean

自動化裝配技術最爲便利,Spring從兩個角度實現自動化裝配。spring

  • 組件掃描:Spring會自動發現應用上下文中所建立的bean
  • 自動裝配:Spring自動知足bean之間的依賴。

自動裝配示例

  • pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.hust.grid.leesf.spring</groupId>
    <artifactId>spring-learning</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring.version>3.1.2.RELEASE</spring.version>
        <cglib.version>3.1</cglib.version>
        <junit.version>4.11</junit.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib-nodep</artifactId>
            <version>${cglib.version}</version>
        </dependency>

    </dependencies>

</project>
  • CompactDisc
package ch2;

interface CompactDisc {
  void play();
}

其只定義了一個play接口,由子類實現。apache

  • SgtPeppers
package ch2;

import org.springframework.stereotype.Component;

@Component
public class SgtPeppers implements CompactDisc {

  private String title = "Sgt. Pepper's Lonely Hearts Club Band";  
  private String artist = "The Beatles";
  
  public void play() {
    System.out.println("Playing " + title + " by " + artist);
  }

}

SgtPeppers繼承了CompactDisc接口,使用Component註釋爲一個Beanmaven

  • CDPlayerConfig
package ch2;

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

@Configuration
@ComponentScan("ch2")
public class CDPlayerConfig {

}

配置類,Spring會自動加載上下文並掃描ch2包下的全部beanide

  • CDPlayerTest
package ch2;

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 org.junit.Assert.assertNotNull;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CDPlayerConfig.class)

public class CDPlayerTest {
    @Autowired
    private CompactDisc cd;

    @Test
    public void cdShouldNotNull() {
        assertNotNull(cd);
    }
}

該類用於測試是否成功裝配CompactDiscbean,測試成功。函數

設置Bean名稱

上述示例中bean的名稱默認爲sgtPeppers,即將類名的首字母小寫,固然可經過@Component("sp")設置其名稱爲sp;或者使用@Named("sp")進行設置。學習

設置組建掃描基礎包

上述示例中指定掃描ch2包,這是經過@ComponentScan("ch")指定的,固然能夠經過@ComponentScan(basePackages="ch2")進行設置。若設置多個包,則可採用@ComponentScan(basePackages={"ch2","video"})方式進行設置。除了使用字符串格式代表包名,也可以使用類名格式,如@ComponentScan(basePackageClasses = SgtPeppers.class)指定掃描類。測試

設置自動裝配

示例中使用@Autowired實現自動裝配,Spring應用上下文中尋找某個匹配的bean,因爲示例中CompactDisc只有一個聲明爲bean的子類,如有多個聲明爲bean的子類,則會報錯,若沒有子類,也會報錯。@Autowired註解不只能夠用在屬性上,也能夠用在構造函數上,還能夠用在Setter方法上。若使用@Autowired(required=false)時,那麼沒有符合的bean時不會報錯,而是處於未裝配的狀態,要防止空指針狀況,其與@Inject註解功能相似。ui

  • 構造函數使用@Autowired註解
@Component
public class CDPlayer implements MediaPlayer {
    private CompactDisc cd;
    
    @Autowired
    public CDPlayer(CompactDisc cd) {
        this.cd = cd;
    }

    public void play() {

    }
}
  • Setter方法使用@Autowired註解
@Autowired
public void setCompactDisc(CompactDisc cd) {
    this.cd = cd;
}

在Java中顯式配置

在配置類中顯式配置bean,將CDPlayerConfig中的@ComponentScan("ch2")移除,此時運行測試用例會報錯,下面經過顯式配置方法來配置bean。修改CDPlayerConfig代碼以下。

package ch2;

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

@Configuration
public class CDPlayerConfig {
    @Bean
    public CompactDisc sgtPeppers() {
        return new SgtPeppers();
    }
}

上述生成的bean名稱與方法名相同,若想設置名稱,可經過@Bean(name=sp)進行設置。對於以下代碼,調用sgtPeppers會生成同一個sgtPeppersbean,這是因爲sgtPeppers方法標記爲BeanSpring會攔截全部對該方法的調用,而且返回一個已經建立的bean實例。默認狀況下,Spring中的bean都是單例的

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

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

還可使用以下方法來引用bean

@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc) {
    return new CDPlayer(compactDisc);
}

這樣會自動裝配一個CompactDisc到配置方法中,不用明確使用sgtPeppers方法來構造CDPlayer

經過xml裝配bean

除了使用JavaConfig來顯式裝配bean外,還可使用xml文件來裝配bean。若想在xml中聲明一個bean元素,則須要以下操做。

<?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"
  xmlns:c="http://www.springframework.org/schema/c"
  xmlns:p="http://www.springframework.org/schema/p"
  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="sgtPeppers" class="ch2.SgtPeppers" />

</beans>

上述xml文件中聲明瞭一個名爲sgtPeppersbean,會調用SgtPeppers的默認構造函數建立bean

使用構造器注入初始化bean

使用constructor-arg元素
<bean id="cdPlayer" class="ch2.CDPlayer">
    <constructor-arg ref="compactDisc"/>
</bean>

上述代碼表示將IDcompactDiscbean引用傳遞到CDPlayer的構造器中。

使用c-命令空間
<bean id="cdPlayer" class="ch2.CDPlayer"
    c:cd-ref="compactDisc"/>
</bean>

其中c:表示命名空間前綴;cd表示構造器參數名;-ref表示注入的bean的引用;compactDisc表示要注入的beanID

將字面量注入到構造器中
<bean id="compactDisc" class="ch2.BlankDisc">
    <constructor-arg value="Sgt. Pepper's Lonely Hearts Club Band" />
    <constructor-arg value="The Beatles" />

或者使用

<bean id="compactDisc" class="ch2.BlankDisc"
    <c:_title="Sgt. Pepper's Lonely Hearts Club Band" />
    <c:artist="The Beatles" />
裝配集合到構造器中
裝配字面量到List集合
<bean id="compactDisc" class="ch2.BlankDisc">
    <constructor-arg value="Sgt. Pepper's Lonely Hearts Club Band" />
    <constructor-arg value="The Beatles" />
    <constructor-arg>
        <list>
            <value>Sgt.AA</value>
            <value>Sgt.BB</value>
            <value>Sgt.CC</value>
        </list>
    </constructor-arg>
</bean>
裝配引用List集合
<bean id="compactDisc" class="ch2.BlankDisc">
    <constructor-arg value="Sgt. Pepper's Lonely Hearts Club Band" />
    <constructor-arg value="The Beatles" />
    <constructor-arg>
        <list>
            <ref bean="sgtPeppers"/>
            <ref bean="whiteAlbum"/>
            <ref bean="revolver"/>
        </list>
    </constructor-arg>
</bean>

同理,對於Set集合只需修改listset便可。

設置屬性

使用xml設置屬性
<bean id="cdPlayer" class="ch2.CDPlayer">
    <property name="compactDisc" ref="compactDisc">
</bean>
使用p-命令空間進行裝配
<bean id="cdPlayer" class="ch2.CDPlayer"
    p:compactDisc-ref="compactDisc">
</bean>

其組成與c-相似。

將字面量裝配到屬性中
<bean id="compactDisc" class="ch2.BlankDisc">
    <property name="title" value="Sgt. Pepper's Lonely Hearts Club Band" />
    <property name="artist"value="The Beatles" />
    <property name="tracks">
        <list>
            <value>Sgt.AA</value>
            <value>Sgt.BB</value>
            <value>Sgt.CC</value>
        </list>
    </property>
</bean>
使用p-裝配屬性
<bean id="compactDisc" class="ch2.BlankDisc">
    <p:title="Sgt. Pepper's Lonely Hearts Club Band" />
    <p:artist="value="The Beatles" />
    <property name="tracks">
        <list>
            <value>Sgt.AA</value>
            <value>Sgt.BB</value>
            <value>Sgt.CC</value>
        </list>
    </property>
</bean>
使用util-命名空間裝配集合
<util:list id="tractList">
    <value>Sgt.AA</value>
    <value>Sgt.BB</value>
    <value>Sgt.CC</value>
</util:list>

此時對應修改以下

<bean id="compactDisc" class="ch2.BlankDisc">
    <p:title="Sgt. Pepper's Lonely Hearts Club Band" />
    <p:artist="value="The Beatles" />
    <p:tracks-ref="trackList" />
</bean>

導入和混合配置

在JavaConfig中引用xml配置

BlankDiscCDPlayerConfig中剝離出來,放置在本身的配置文件CDConfig中。此時須要在CDPlayerConfig中使用@Import(CDConfig.class)將二者組合;或者使用更高級別的Config中使用@Import({CDPlayerConfig.class,CDConfig.class})組合二者。若將BlankDisc配置在cd-config.xml文件中,則可以使用@ImportResource("classpath:cd-config.xml")導入。

在xml配置中引用JavaConfig

可使用import元素引用配置,如

<import resource="cd-config.xml" />

總結

Spring有三種方式裝配bean,使用自動化裝配技術使得代碼更簡潔;而且有多種方式注入屬性。

相關文章
相關標籤/搜索