控制反轉(zhuǎn)IOC(DI依賴注入)

Spring具有非常大的靈活性,它提供了三種主要的裝配機制:

  • 在XML中進(jìn)行顯式配置。
  • 在Java中進(jìn)行顯式配置。
  • 隱式的bean發(fā)現(xiàn)機制和自動裝配。
一、自動化裝配bean

Spring從兩個角度來實現(xiàn)自動化裝配:

  • 組件掃描(component scanning):Spring會自動發(fā)現(xiàn)應(yīng)用上下文中所創(chuàng)建的bean。
  • 自動裝配(autowiring):Spring自動滿足bean之間的依賴。

1.首先創(chuàng)建CompactDisc.java文件,里面頂一個一個接口:

package com.df.test.service.impl;

public interface CompactDisc {
    void play();
}

2.然后定義它的實現(xiàn)類:

package com.df.test.service.impl;

import org.springframework.stereotype.Component;

@Component
public class SgtPeppers implements CompactDisc {

    public void play() {
        // TODO Auto-generated method stub
        System.out.println("播放音樂...");
    }

}

需要注意的就是SgtPeppers類上使用了@Component注解。這個簡單的注解表明該類會作為組件類,并告知Spring要為這個類創(chuàng)建bean。沒有必要顯式配置SgtPeppersbean,因為這個類使用了@Component注解,所以Spring會為你把事情處理妥當(dāng)。不過,組件掃描默認(rèn)是不啟用的。我們還需要顯式配置一下Spring,從而命令它去尋找?guī)в蠤Component注解的類,并為其創(chuàng)建bean。如下設(shè)置Spring對組件進(jìn)行掃描:

package com.df.test.service.impl;

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

@Configuration
@ComponentScan
public class CDPlayerConfig {

}

使用了@ComponentScan注解,這個注解能夠在Spring中啟用組件掃描。如果沒有其他配置的話,@ComponentScan默認(rèn)會掃描與配置類相同的包。因為CDPlayerConfig類位于com.df.test.service.impl包中,因此Spring將會掃描這個包以及這個包下的所有子包,查找?guī)в蠤Component注解的類。并且會在Spring中自動為其創(chuàng)建一個bean。
當(dāng)然也可以XML來啟用組件掃描:

<context:component-scan base-package="com.df.test.service.impl" />

測試代碼如下:

package com.df.test;

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 com.df.test.service.impl.CDPlayerConfig;
import com.df.test.service.impl.CompactDisc;
import com.df.test.service.impl.SgtPeppers;

@RunWith(SpringJUnit4ClassRunner.class) //表示繼承了SpringJUnit4ClassRunner類
@ContextConfiguration(classes= CDPlayerConfig.class)
public class JavaTestMethod {
    @Autowired CompactDisc cd;//這里,不論我是用CompactDisc接口還是SgtPeppers實現(xiàn)類,下面都有輸出,都是同一個對象SgtPeppers。
    
    @Test
    public void testMethod() {
        cd.play();
    }
}

@Component基本使用。
Spring應(yīng)用上下文中所有的bean都會給定一個ID。在前面的例子中,盡管我們沒有明確地為SgtPeppersbean設(shè)置ID,但Spring會根據(jù)類名為其指定一個ID。具體來講,這個bean所給定的ID為sgtPeppers,也就是將類名的第一個字母變?yōu)樾?。我們也可以給bean命名,像下面代碼這樣。有時候可以用@Named代替@Component使用:

@Component("myComponentName")
public class SgtPeppers implements CompactDisc {
          ...
}

@ComponentScan基本使用。
不但可以默認(rèn)設(shè)置,還可以指定多個不同的基礎(chǔ)包作為掃描對象,使用basePackages屬性,String[]類型。
另外一種方法,那就是將其指定為包中所包含的類或接口,使用 basePackageClasses屬性,這些類所在的包將會作為組件掃描的基礎(chǔ)包。,Class<?>[]類型:

//一下兩種方法,任意一種都可以實現(xiàn)

@Configuration
@ComponentScan(basePackages = {"com.df.test.service.impl","com.df.test.dao"})
public class CDPlayerConfig {

}

@Configuration
@ComponentScan(basePackageClasses = {SgtPeppers.class})
public class CDPlayerConfig {

}

@Autowired 實現(xiàn)自動裝配。
簡單來說,自動裝配就是讓Spring自動滿足bean依賴的一種方法,在滿足依賴的過程中,會在Spring應(yīng)用上下文中尋找匹配某個bean需求的其他bean。假如有且只有一個bean匹配依賴需求的話,那么這個bean將會被裝配進(jìn)來。如果沒有匹配的bean,那么在應(yīng)用上下文創(chuàng)建的時候,Spring會拋出一個異常。因為是按照類型進(jìn)行匹配,所以如果有多個bean都能滿足依賴關(guān)系的話,Spring將會拋出一個異常,表明沒有明確指定要選擇哪個bean進(jìn)行自動裝配。@Autowired注解不僅能夠用在構(gòu)造器上,還能用在屬性的Setter方法上,還可以在屬性上。如下代碼,下面三個屬性對象,都會完成自動裝配,可以用@Inject在大多數(shù)情況下來代替@Autowired 。@Named和@Inject來源于Java依賴注入規(guī)范。

package com.df.test.service.impl;

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

@Component
public class CDPlayer {

    @Autowired 
    private CompactDisc cd;
    
    private CompactDisc cd2;
    
    private CompactDisc cd3;

    @Autowired 
    public CDPlayer(CompactDisc cd2) {
        this.cd2 = cd2;
    }
    
    @Autowired 
    public void setCd3(CompactDisc cd3) {
        this.cd3 = cd3;
    }
    
    public void play(){
        cd.play();
        cd2.play();
        cd3.play();
    }   
}

二、通過Java代碼裝配bean

通過JavaConfig顯式配置Spring:

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

@Configuration
public class CDPlayer02 {
    
    @Bean
    public CompactDisc getBeanI(){
        return new SgtPeppers();
    }
}

@Bean注解基本使用。
創(chuàng)建JavaConfig類的關(guān)鍵在于為其添加@Configuration注解,@Configuration注解表明這個類是一個配置類,該類應(yīng)該包含在Spring應(yīng)用上下文中如何創(chuàng)建bean的細(xì)節(jié)。@Bean注解會告訴Spring這個方法將會返回一個對象,該對象要注冊為Spring應(yīng)用上下文中的bean。方法體中包含了最終產(chǎn)生bean實例的邏輯。所以這里就很靈活了,可以一個方法,返回很多個不同的對象根據(jù)不同的邏輯條件。默認(rèn)情況下,bean的ID與帶有@Bean注解的方法名是一樣的。也可以通過name屬性指定一個不同的名字。

三、通過XML裝配bean

Spring剛出來的時候,就是以這種方式。所以這里就不做過多解釋了??梢酝ㄟ^set方法注入,也可以通過構(gòu)造方法注入。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean id="customerDAO" class="com.sanxin.org.jdbc.JdbcCustomerDAO">
        <property name="dataSource" ref="dataSource" />
    </bean>

</beans>

我是分割線


混合配置

以上已經(jīng)將三種裝配bean的 方式講完了,現(xiàn)在說說混合配置
1.JavaConfig配置之間相互引用
假設(shè)由于有兩個JavaConfig配置的類:

@Configuration
public class CDPlayer02 {
    @Bean
    public CompactDisc getBean02(){
        return new SgtPeppers02();
    }
}
@Configuration
public class CDPlayer01 {
    @Bean
    public CompactDisc getBea01(){
        return new SgtPeppers01();
    }
}

我們需要有一種方式將這兩個類組合在一起,可以這樣做,使用@Import:

@Configuration
@Import(CDPlayer02 .class)
public class CDPlayer01 {
    @Bean
    public CompactDisc getBea01(){
        return new SgtPeppers01();
    }
}

也可以干脆這樣:

@Configuration
@Import({CDPlayer01 .class,CDPlayer2 .class})
public class CDPlayer01 {
}

2.在JavaConfig中引用XML配置
假設(shè)有cd-config.xml配置文件

@Configuration
@Import(CDPlayer02 .class)
@ImportResource("classpath:cd-config.xml")
public class CDPlayer01 {
    @Bean
    public CompactDisc getBea01(){
        return new SgtPeppers01();
    }
}

3.在XML配置中引用JavaConfig

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
     <!--  這就是那個JavaConfig配置類 -->
    <bean class = "com.df.test.service.impl.CDConfig"/> 

    <bean id="customerDAO" class="com.sanxin.org.jdbc.JdbcCustomerDAO">
        <property name="dataSource" ref="dataSource" />
    </bean>

</beans>

4.在XML配置中引用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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
     <!--  這就是那個JavaConfig配置類 -->
    <bean class = "com.df.test.service.impl.CDConfig"/> 
    <!--  這就是另一個那個xml配置文件 -->
    <improt resource = "cdplayer-config.xml" />

</beans>

以上就是bean裝配的三種方式。上一篇Spring容器

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容