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();
}
}
由上述程式碼,我們可以看出:
- @Controller(“名稱”)用來取代”bean”標籤及其屬性,“名稱”取代“id”,”寫在類頭上”取代“calss”。
- @Autowired用來取代property標籤及屬性value,@Qualifier(“名稱”)用來取代屬性ref。
總結
xml和@,這兩種方式在實際開發中都會用到,各有各的方便之處。一般地,3層介面之間的注入關係,和springMVC中的url對映用@。而spring在事務管理,以及整合mybatis時的資料庫連線池配置,SqlSessionFactory等的配置時用xml。