理解Spring中的IoC和DI


什么是IoC和DI

IoC(Inversion of Control 控制反轉):是一種面向對象編程中的一種設計原則,用來減低計算機代碼之間的耦合度。其基本思想是:借助於“第三方”實現具有依賴關系的對象之間的解耦。

DI(Dependence Injection 依賴注入):將實例變量傳入到一個對象中去(Dependency injection means giving an object its instance variables)。

  • 控制反轉是一種思想
  • 依賴注入是一種設計模式
  • IoC框架使用依賴注入作為實現控制反轉的方式

為什么需要

在沒有IoC之前,我們要在A類中使用B類,就要在A類中newB類的實例,這樣A類和B類之間就出現了耦合。

public class A {
    private B b = new B();
}

使用了IoC之后,我們就把實例化這樣操作交給框架去幫我們做了。

Spring 中的IoC

容器是Spring的核心,Spring容器負責創建應用程序中的bean並通過DI來協調這些對象之間的關系。

Spring容器並不是只有一個,Spring自帶多個容器的實現,可以歸納為兩種不同的類型:

  1. bean工廠(BeanFactory),最簡單的容器,提供基本的DI支持。
  2. 應用上下文(ApplicationContext),繼承了BeanFactory,並提供應用框架級別的服務。

作為開發人員,我們需要告訴Spring哪些對象要作為bean裝配到容器中,bean和bean之間的依賴關系。Spring提供了三種主要的裝配機制:

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

下面我們逐一介紹這三種機制。

自動裝配bean

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

@Component 注解表明該類會作為組件類,並告知Spring要為這個類創建bean。

@Component
public class Dog {

}

@ComponentScan 注解啟用了組件掃描。

@Configuration
@ComponentScan
public class DemoApplication {

}

自動裝配:Spring自動滿足bean之間的依賴

@Autowired 注解可以作用在構造器、方法、屬性上。

@Component
public class Dog {
  	// 屬性
    @Autowired
    private Cat cat;

  	// 構造器
    // 從Spring 4.3開始,具有單個構造函數的類可以省略@Autowired注釋
    @Autowired
    public Dog(Cat cat) {
        this.cat = cat;
    }

  	// 方法
    @Autowired
    public void setCat(Cat cat) {
        this.cat = cat;
    }
}

在Java中裝配bean

組價配置:聲明一個配置類,並在配置類中配置bean

@Configuration 注解表明這個類是配置類,我們可以在配置類下創建bean。

@bean 注解會告訴Spring這個方法將會返回一個對象,該對象要注冊為Spring上下文中的bean。

/**
 * 普通類
 */
public class BaseBean {

    public void p() {
        System.out.println("Hello bean");
    }
}



/**
 * 配置類
 */
@Configuration
public class BeanConfig {

  	// 這個方法返回一個對象,Spring會把這個對象注冊為bean
    @Bean
    public BaseBean getBaseBean() {
        return new BaseBean();
    }

}

組件注入:在配置類中把被依賴的組件注入另一個組件中

兩種方式注入bean:

  1. 我們可以直接調用get方法,獲取到對應的組件
  2. get方法中把被依賴的組件作為參數傳入,Spring在調用這個方法時,會自動為你注入。
/**
 * 普通類
 */
public class BaseBean {

    public void p() {
        System.out.println("Hello bean");
    }
}

/**
 * 普通類
 */
public class UserBean {
    private BaseBean baseBean;

    public UserBean(BaseBean baseBean) {
        this.baseBean = baseBean;
    }
}



/**
 * 配置類
 */
@Configuration
public class BeanConfig {

    // 這個方法返回一個對象,Spring會把這個對象注冊為bean
    @Bean
    public BaseBean getBaseBean() {
        return new BaseBean();
    }

    /**
     * 以下為兩種注入bean的方法
     */
  	// 方法一:直接調用get方法
    @Bean
    public UseBean getUseBean() {
        return new UseBean(getBaseBean());
    }

  	// 方法二:當做參數傳入,Spring將自動為你注入
    @Bean
    public UseBean getUseBean(BaseBean baseBean) {
        return new UseBean(baseBean);
    }

}

通常情況下我們都會使用方法二。

通過XML裝配bean

盡管現在我們已經不再怎么使用XML裝配bean,但在Spring剛剛出現的時候,XML是描述配置的主要方式,我們還是有必要了解一下的。

在使用JavaConfig的時候,我們創建了一個配置類來裝配bean,而在XML配置中,我們需要創建一個XML文件,並且要以<beans>元素為根。

最為簡單的Spring 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.xsd">

    <!-- 在這里配置你的bean -->

</beans>

組件配置

以上文的BaseBean為例,我們在XML文件中把它聲明為bean。

<bean id="baseBean" class="com.example.demo.BaseBean" />

組件注入

<bean id="useBean" class="com.example.demo.UseBean"
      c:_="baseBean" />

XML的語法我就不再這里詳述了,有興趣的同學可以自行學習。

總結

本文我們簡單介紹了Spring中的IoC,介紹了Spring中裝配bean的三種方式:自動化配置,基於Java的顯式配置以及基於XML的顯式配置。這些技術都是為了描述Spring應用中的組件以及組件之間的關系。

一般來說我們都會使用自動化配置,盡量避免顯式配置帶來的維護成本。如果不得不使用顯式配置的話,我們優先選擇基於Java的配置,它比基於XML的配置更加強大、類型安全並且易於重構。

參考資料

控制反轉(IoC)與依賴注入(DI)

Spring 實戰

Spring 揭秘

原文首發在我的簡書 https://www.jianshu.com/p/7f7e089f4909


免責聲明!

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



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