1. 程式人生 > >Spring學習(1):控制反轉(IoC)和依賴注入(DI)的詳解以及註解(annotation)開發入門案例

Spring學習(1):控制反轉(IoC)和依賴注入(DI)的詳解以及註解(annotation)開發入門案例

前言

以往的java學習中,我們要想得到一個物件,就把它new出來。如:Apple apple = new Apple();

在一些複雜的系統中,一個物件A可能依賴於物件B,C等(程式碼表現為A類持有B,C類的物件作為A類的屬性)。以往來說,我們想要使用B,C中的方法時,就要先new出BC的物件,再去呼叫方法。回頭想想,我們真的有必要去主動獲取依賴物件嗎?我們的最終目的,其實就是直接呼叫依賴物件所提供的方法而已。只要用到這個依賴物件時,它能及時就緒,我們完全不用管這個物件是從哪裡來的。

我們並不想在A類中new出B,C的物件,這樣會增加類之間的耦合性。於是,就有了控制反轉(IoC)和依賴注入(DI)的概念。控制反轉就是將物件的例項化過程交給spring框架來做,依賴注入就是將A物件所依賴的BC物件以配置檔案或註解的形式傳遞給A物件。

正文

spring實現控制反轉和依賴注入的方式有2種,一種使用xml配置檔案,另一種使用註解。

一,使用xml檔案配置

基於xml的開發以經典的web三層結構為例。我們知道,action動作類中持有service類的物件,service類中又持有dao類的物件,傳統方式如下:
這裡寫圖片描述
如上圖所示,我們理所當然的new出所依賴的物件例項,這樣各個類之間的耦合性太強,不利於維護。spring提供了2種思想(IoC和DI),將“new出物件的動作”和“產生依賴關係”的操作配置到配置檔案中。如下圖:
這裡寫圖片描述
上圖所示,原始碼中並不再出現“new”關鍵字來建立例項,而是在配置檔案(這裡是xml檔案)中用bean標籤來建立,物件之間的依賴關係則用“bean”標籤下的“property”標籤來引用。這樣一來,各個類之間的耦合性就解除了,各個類都和配置檔案打交道。

二,使用註解開發

使用註解前,我們要在spring的核心配置檔案中新增名稱空間,讓spring掃描指定包路徑下含有註解的類。

<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"
>
<!-- 下面context名稱空間的作用是掃描類路徑下的類,通過相應的註解建立bean並注入依賴 --> <context:component-scan base-package="com.jimmy.zhujie"></context:component-scan> </beans>

然後,我們就不要在xml檔案中配置bean啦,而是在具體類和依賴屬性前面加註解。

其中,spring框架針對web3層結構分別為我們提供了3個註解:@Repository,@Service,@Controller。分別用於註解dao實現類,service實現類,controller實現類。@Autowired用於註解依賴物件,這樣spring就為我們尋找並自動注入依賴類。而當dao或service介面的實現類有多個的話,就要用名字來區別,@Autowired就要結合@Qualifier(“名字”)來使用。下面是一個註解開發的例子。

1,編寫dao介面和實現類

package com.jimmy.zhujie;

import org.springframework.stereotype.Repository;

@Repository("daoImpl")
public class UserDaoImpl implements UserDao{

    public void save() {
        System.out.println("新增一個使用者");
    }
}

2,編寫service介面和實現類

package com.jimmy.zhujie;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service("serviceImpl")
public class UserServiceImpl implements UserService{

    @Autowired
    @Qualifier("daoImpl")
    private UserDao uu;

    public void addUser() {
        this.uu.save();
    }
}

3,編寫web層的controller類

package com.jimmy.zhujie;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;

@Controller("myController")
public class MyController {

    @Autowired
    @Qualifier("serviceImpl")
    private UserService userService;

    public void addUser(){
        userService.addUser();
    }
}

4,編寫測試類

package com.jimmy.zhujie;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class testIoC {
    @Test
    public void test1(){
        String xmlPath = "com/jimmy/zhujie/applicationContext.xml"; //預設從src路徑下讀檔案
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);

        MyController uuu= (MyController) applicationContext.getBean("myController");
        uuu.addUser();
    }
}

由上述程式碼,我們可以看出:

  1. @Controller(“名稱”)用來取代”bean”標籤及其屬性,“名稱”取代“id”,”寫在類頭上”取代“calss”。
  2. @Autowired用來取代property標籤及屬性value,@Qualifier(“名稱”)用來取代屬性ref。

總結

xml和@,這兩種方式在實際開發中都會用到,各有各的方便之處。一般地,3層介面之間的注入關係,和springMVC中的url對映用@。而spring在事務管理,以及整合mybatis時的資料庫連線池配置,SqlSessionFactory等的配置時用xml。