【Spring】Spring的bean裝配


前言

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

裝配bean

Spring在裝配bean時非常靈活,其提供了三種方式裝配bean

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

自動化裝配bean

自動化裝配技術最為便利,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接口,由子類實現。

  • 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注釋為一個Bean

  • CDPlayerConfig

package ch2;

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

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

}

配置類,Spring會自動加載上下文並掃描ch2包下的所有bean

  • 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注解功能類似。

  • 構造函數使用@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,使用自動化裝配技術使得代碼更簡潔;並且有多種方式注入屬性。


免責聲明!

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



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