第 1 章 Spring 的基本應(yīng)用

Spring 是當前主流的 Java Web 開發(fā)框架盒齿,它是為了解決企業(yè)應(yīng)用開發(fā)的復(fù)雜性問題而產(chǎn)生 的方妖。 對于一個 Java 開發(fā)者來說,掌握 Spring 框架的使用,已是其必備的技能之一稀火。 本章將對 Spring 框架的基礎(chǔ)知識進行詳細的講解。

Spring 概述
  • 什么是 Spring
  • Spring 是由 Rod Johnson 組織和開發(fā)的一個分層的 Java SE/EE fu川一stack (一站式)輕量 級開源框架赌朋,它以 loC ( Inversion of Control 凰狞,控制反轉(zhuǎn))和 AOP ( Aspect Oriented Programming , 面向切面編程)為內(nèi)核,使用基本的 JavaBean 來完成以前只可能由 EJB ( Enterprise Java Beans , Java 企業(yè) Bean) 完成的工作沛慢,取代了 EJB 的靡腫赡若、 低效的開發(fā)模式。
  • Spring 致力于 Java EE 應(yīng)用各層的解決方案逾冬,在表現(xiàn)層它提供了 Spring MVC 以及與 Struts 框架的整合功能;在業(yè)務(wù)邏輯層可以管理事務(wù)躺苦、 記錄日志等;在持久層可以整合 MyBatis、 Hibernate匹厘、 JdbcTemplate 等技術(shù)嘀趟。 因此愈诚,可以說 Spring 是企業(yè)應(yīng)用開發(fā)很好的"一站式"選 擇牛隅。 雖然 Spring 貫穿于表現(xiàn)層、 業(yè)務(wù)邏輯層和持久層酌泰,但它并不想取代那些已有的框架,而是 以高度的開放性與它們進行無縫整合丈攒。
  • Spring 框架的優(yōu)點

Spring 具有簡單授霸、可測試和松輯合等特點,從這個角度出發(fā)显设, Spring 不僅可以用于服務(wù)器 端開發(fā)辛辨,也可以應(yīng)用于任何 Java 應(yīng)用的開發(fā)中斗搞。 關(guān)于 Spring 框架優(yōu)點的總結(jié),具體如下允悦。

  • 非侵入式設(shè)計
    Spring 是一種非侵入式( non-invasive )框架虑啤,它可以使應(yīng)用程序代碼對框架的依賴 狞山、最小化。
  • 方便解耦总珠、 簡化開發(fā)
    Spring 就是一個大工廠勘纯,可以將所有對象的創(chuàng)建和依賴關(guān)系的維護工作都交給 Spring 容器 管理屡律,大大地降低了組件之間的搞合性。
  • 支持 AOP
    Spring 提供了對 AOP 的支持搏讶,它允許將一些通用任務(wù),如安全媒惕、 事務(wù)妒蔚、 曰志等進行集中式 處理,從而提高了程序的復(fù)用性科盛。
  • 支持聲明式事務(wù)處理
    只需要通過配置就可以完成對事務(wù)的管理菜皂,而無須手動編程恍飘。
  • 方便程序的測試
    Spring 提供了對 Junit4 的支持,可以通過注解方便地測試 Spring 程序母蛛。
  • 方便集成各種優(yōu)秀框架
    Spring 不排斥各種優(yōu)秀的開源框架乳怎,其內(nèi)部提供了對各種優(yōu)秀框架(如 Struts舞肆、 Hibernate、 MyBatis、 Quartz 等)的直接支持剃根。
  • 降低 Java EE API 的使用難度
    Spring 對 Java EE 開發(fā)中非常難用的一些 API (如 JDBC狈醉、 JavaMail 等),都提供了封裝抒线, 使這些 API 應(yīng)用難度大大降低渣慕。
  • Spring 的體系結(jié)構(gòu)

Spring 框架采用的是分層架構(gòu),它一系列的功能要素被分成 20 個模塊抑进,這些模塊大體分為 Core Container睡陪、 Data Access/lntegration兰迫、 Web、 AOP (Aspect Oriented Programming)涡拘、 Instrwmentation, Messaging 和 Test 须鼎,如圖所示晋控。



在圖中,包含了 Spring 框架的所有模塊仲吏,其中裹唆,灰色背景模塊為本書中所涉及的主要 模塊只洒。 接下來分別對體系結(jié)構(gòu)中的模塊作用進行簡單介紹毕谴,具體如下。

  1. Core Container (核心窯器)
    Spring 的核心容器是其他模塊建立的基礎(chǔ)循帐,它主要由 Beans 模塊舀武、 Core 模塊银舱、 Context 模 塊跛梗、 Context-support 模塊和 SpEL ( Spring Expression Language , Spring 表達式語言)模塊 組成柿顶,具體介紹如下嘁锯。
    ? Beans 模塊:提供了 BeanFactory,是工廠模式的經(jīng)典實現(xiàn)蝗羊, Spring 將管理對象稱為 Bean耀找。
    ? Core 核心模塊:提供了 Spring 框架的基本組成部分业崖,包括 loC 和 DI 功能双炕。
    ? Context 上下文模塊: 建立在 Core 和 Beans 模塊的基礎(chǔ)之上,它是訪問定義和配置的任 何對象的媒介摇锋。 其中 ApplicationContext 接口是上下文模塊的焦點站超。
    ? Context-support 模塊:提供了對第三方庫嵌入 Spring 應(yīng)用的集成支持死相,比如緩存 ( EhCache、 Guava双肤、 JCache)钮惠、 郵件服務(wù) (JavaMail)素挽、 任務(wù)調(diào)度( CommonJ狸驳、 Quartz) 和模 板引擎( FreeMarker、 JasperReports酥馍、 速率)阅酪。
    ? SpEL 模塊:是 Spring 3.0 后新增的模塊术辐,它提供了 Spring Expression Language 支持, 是運行時查詢和操作對象圖的強大的表達式語言必孤。
  2. Data Access/lntegration (戴帽訪問l集成)
    數(shù)據(jù)訪問/集成層包括 JDBC敷搪、 ORM 幢哨、 OXM嘱么、 JMS 和 Transactions 模塊曼振,真體介紹如下。
    ? JDBC 模塊:提供了一個 JDBC 的抽象層映胁,大幅度地減少了在開發(fā)過程中對數(shù)據(jù)庫操作的 編碼甲雅。
    ? ORM 模塊:對流行的對象關(guān)系映射 API 抛人,包括 JPA妖枚、 JDO 和 Hibernate 提供了集成層支持。
    ? OXM 模塊:提供了一個支持對象/XML 映射的抽象層實現(xiàn)荠商,如 JAXB莱没、 Castor、 XMLBeans牙咏、 JiBX 和 XStream眠寿。
    ? JMS 模塊:指 Java 消息傳遞服務(wù)焦蘑,包含使用和產(chǎn)生信息的特性例嘱,自 4. 1 版本后支持與 Spring-message 模塊的集成拼卵。
    ? Transactions 事務(wù)模塊:支持對實現(xiàn)特殊接口以及所有 POJO 類的編程和聲明式的事 務(wù)管理。
  3. Web
    Spring 的 Web 層包括 WebSocket雀彼、 Servlet徊哑、 Web 和 Portlet 模塊聪富,具體介紹如下墩蔓。
    ? WebSocket 模塊: Spring 4.0 以后新增的模塊,它提供了 WebSocket 和 SockJS 的實現(xiàn)昏名, 以及對 STOMP 的支持葡粒。
    ? Servlet 模塊:也稱為 Spring-webmvc 模塊嗽交,包含了 Spring 的模型一視圖一控制器(MVC) 和 REST Web Services 實現(xiàn)的 Web 應(yīng)用程序颂斜。
    ? Web 模塊:提供了基本的 Web 開發(fā)集成特性沃疮,例如: 多文件上傳功能司蔬、 使用 Servlet 監(jiān) 聽器來初始化 loC 容器以及 Web 應(yīng)用上下文。
    ? Portlet 模塊:提供了在 Portlet 環(huán)境中使用 MVC 實現(xiàn)肺缕,類似 Servlet 模塊的功能同木。
  4. 其他模塊
    Spring 的其他模塊還有 AOP彤路、 Aspects芥映、 Instrumentation 以及 Test 模塊奈偏,具體介紹如下。
    ? AOP 模塊:提供了面向切面編程實現(xiàn)姆吭,允許定義方法攔截器和切入點内狸,將代碼按照功能 進行分離昆淡,以降低搞合性刽严。
    ? Aspects 模塊:提供了與 AspectJ 的集成功能, AspectJ 是一個功能強大且成熟的面向切 面編程 (AOP) 框架管削。
    ? Instrumentation 模塊:提供了類工具的支持和類加載器的實現(xiàn)含思,可以在特定的應(yīng)用服務(wù)器 中使用甘晤。
    ? Messaging 模塊: Spring 4.0 以后新增的模塊线婚,它提供了對消息傳遞體系結(jié)構(gòu)和協(xié)議 的支持塞弊。
    ? Test 模塊:提供了對單元測試和集成測試的支持。
  • Spring 的下載及目錄結(jié)構(gòu)

Spring 的第一個版本是在 2004 年發(fā)布的虹脯,經(jīng)過 10 多年的發(fā)展循集, Spring 的版本也在不斷地 升級優(yōu)化中咒彤。我的代碼都是基于Spring 4.3.6編寫實現(xiàn)的镶柱, 建議大家也下載該版本模叙。 Spring 開發(fā)所需的 JAR 包分為兩個部分范咨,具體如下渠啊。

  1. Spring 框架包 Spring 4.3.6 版本的框架壓縮包,名稱為 spring-framework-4.3.6.RELEASE-dist.zip 贯溅,此壓縮包可以通過地址 ''https://repo.spring.io/release/org/springframework/spring/4.3.6.RELEASE/" 下載它浅。 下載完成后罚缕,將壓縮包解壓到自定義的文件夾中邮弹,解壓后的文件目錄結(jié) 構(gòu)如圖所示蚓聘。 在圖的目錄中夜牡, docs 文件夾中包含 Spring 的 API 文檔和開發(fā)規(guī)范j libs 文件夾中包含開發(fā)需要的 JAR 包和源碼 i schema 文件夾中包含開發(fā)所需要的 schema 文件塘装,這些文件中定 義了 Spring 相關(guān)配置文件的約束蹦肴。

    打開 libs 目錄可以看到 60 個 JAR 文件阴幌,如下圖所示。

    從圖中可以看出. libs 目錄中的 JAR 包分為三類,其中以 RELEASE.jar 結(jié)尾的是 Spring 框架 class 文件的 JAR 包;以 RELEASE - javadoc. jar 結(jié)尾的是 Spring 框架 API 文檔的壓縮包; 以 RELEASE-sources.jar 結(jié)尾的是 Spring 框架源文件的壓縮包懒闷。 整個 Spring 框架由 20 個模塊 組成栈幸,該目錄下 Spring 為每個模塊都提供了這三類壓縮包侦镇。
    在 libs 目錄中壳繁,有四個 Spring 的基礎(chǔ)包,它們分別對應(yīng) Spring 核心容器的四個模塊润樱,具體 介紹如下羡棵。
    ? spring-core-4.3.6.RELEASE.jar: 包含 Spring 框架基本的核心工具類皂冰, Spring 其他組件 都要用到這個包里的類秃流,是其他組件的基本核心舶胀。
    ? spring-beans-4.3.6.RELEASE.jar: 所有應(yīng)用都要用到的 JAR 包,它包含訪問配置文件糖赔、 創(chuàng)建和管理 Bean 以及進行 Inversion of Control(loC)或者 Dependency Injection(DI)操作相關(guān)的 所有類放典。
    ? spring-context -4.3.6.RELEASE.jar: Spring 提供了在基礎(chǔ) loC 功能上的擴展服務(wù)刻撒,還提 供了許多企業(yè)級服務(wù)的支持声怔,如郵件服務(wù)醋火、任務(wù)調(diào)度箱吕、 JNDI 定位茬高、 EJB 集咸怎栽、遠程訪問、緩存 以及各種視圖層框架的封裝等谬以。
    ? spring-expression-4.3.6.RELEASE.jar: 定義了 Spring 的表達式語言由桌。
  2. 第三萬依賴包
    在使用 Spring 開發(fā)時行您,除了要使用自帶的 JAR 包外娃循, Spring 的核心容器還需要依賴 commons.logging 的 JAR 包淮野。 該 JAR 包可以通過網(wǎng)址 "http://commons.apache.org/proper/commons-logging/download_logging.cgi
    " 下載骤星。 下載完成后洞难,會得到一個名為 commonslogging-1 .2-bin.zit 的壓縮包队贱。 將壓縮包解壓到自定義目錄后潭袱,即可找到 commons-Iogging1 .2.jar屯换。
    初學者學習 Spring 框架時彤悔,只需將 Spring 的 4 個基礎(chǔ)包以及 commons-logging-1.2.jar 復(fù)制到項目的 lib 目錄晕窑,并發(fā)布到類路徑中即可杨赤。
Spring 的核心容器

Spring 框架的主要功能是通過其核心容器來實現(xiàn)的,因此在正式學習 Spring 框架的使用之 前挫鸽,有必要先對其核心容器有一定的了解鸥跟。Spring 框架提供了兩種核心容器医咨,分別為 BeanFactory 和 ApPI icationContext拟淮。 本節(jié)中將對這兩種核心容器進行簡單的介紹很泊。

  • BeanFactory

BeanFactory 由 org.springframework.beans.facytory.BeanFactory 接口定義,是基礎(chǔ)類型 的 loC 容器(關(guān)于 loC 的具體含義將在后面的小節(jié)講解委造,這里只需知道其表示控制反轉(zhuǎn))戳鹅, 它提供了完整的 loC 服務(wù)支持。 簡單來說昏兆, BeanFactory就是一個管理 Bean 的工廠枫虏,它主要負 責初始化各種 Bean ,并調(diào)用它們的生命周期方法爬虱。
BeanFactory 接口提供了幾個實現(xiàn)類隶债,其中最常用的是 org.springframework. beans factory.xml.XmIBeanFactory 跑筝,該類會根據(jù) XML 配置文件中的定義來裝配 Bean死讹。
創(chuàng)建 BeanFactory 實例時,需要提供 Spring 所管理容器的詳細配置信息继蜡,這些信息通常采 用 XML 文件形式來管理回俐,其加載配置信息的語法如下。

BeanFactory beanFactory = 
new XmlBeanFactory(new FileSystemResource("F: /applicationContext.xml")) ; 

這種加載方式在實際開發(fā)中并不多用稀并,大家了解即可仅颇。

  • ApplicationContext

ApplicationContext是 BeanFactory 的子接口,也被稱為應(yīng)用上下文碘举,是另一種常用的 Spring 核心容器忘瓦。 它由 org.springframework.context. ApplicationContext 接口定義,不僅包含了 BeanFactory 的所有功能,還添加了對國際化耕皮、資源訪問境蜕、事件傳播等方面的支持。
創(chuàng)建 ApplicationContext 接口實例凌停,通常采用兩種方法粱年,具體如下。

  1. 通過 ClassPathXmlApplicationContext
    創(chuàng)建 ClassPathXmlAp~licationContext 會從類路徑 classPath 中尋找指定的 XML 配置文件罚拟,找到并裝載完成 ApplicationContext 的實例化工作台诗,其使用語法如下。
ApplicationContext applicationContext = 
new ClassPathXmlApplicationContext(String configLocation) ; 

上述代碼中赐俗, configLocation 參數(shù)用于指定 Spring 配置文件的名稱和位置拉队。 如果其值為 "applicationContext.xml" ,則 Spring 會去類路徑中查找名稱為 applicationContext.xml 的配置 文件阻逮。

  1. 通過 FileSystemXmlApplicationContext
    創(chuàng)建 FileSystemXmlApplicationContext 會從指定的文件系統(tǒng)路徑(絕對路徑)中尋找指定的 XML 配置文件粱快,找到并裝載完成 ApplicationContext 的實例化工作,其使用語法如下叔扼。
ApplicationContext applicationContext = 
new FileSystemXmlApplicationContext(String configLocation); 

與 ClassPathXmlApplicationContext 有所不同的是事哭,在讀取 Spring 的配置文件時, FileSystemXmlApplicationContext 不再從類路徑中讀取配置文件瓜富,而是通過參數(shù)指定配置文件 的位置慷蠕,例如 "D:/workspaces/appIicationContext. xml"。 如果在參數(shù)中寫的不是絕對路徑食呻,那 么方法調(diào)用的時候,會默認用絕對路徑來找澎现。 這種采用絕對路徑的方式仅胞,會導(dǎo)致程序的靈活性變差,所以這個方法一般不推薦使用剑辫。
在使用 Spring 框架時干旧,可以通過實例化其中任何一個類來創(chuàng)建 ApplicationContext 容器。 通常在 Java 項目中妹蔽,會采用通過 ClassPathXmlApplicationContext 類來實例化 ApplicationContext 容器的方式椎眯,而在 Web 項目中, ApplicationContext 容器的實例化工作會交由 Web 服務(wù)器來完成 胳岂。 Web 服務(wù)器實例化 ApplicationContext 容器時编整,通常會使用基于 ContextLoaderListener 實現(xiàn)的方式,此種方式只需要在 web.xml 中添加如下代碼乳丰。

<!-- 指定 Spring 配置文件的位置掌测,多個配置文件時,以逗號分隔 --> 
<context-param> 
  <param-name>contextConfigLocation</param-name>
  <!-- Spring 將加載 spring 目錄下的 applicationContext .xml 文件 -->
  <param-value> classpath:spring/applicationContext.xml </param-value>
</context-param> 
<!-- 指定以 ContextLoaderListener 方式啟動 Spring 容器 -->
<listener>
  <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> 
</listener> 

在后面章節(jié)講解三大框架整合以及項目時产园,將采用基于 ContextLoaderListener 的方式 由 Web 服務(wù)器實例化 ApplicationContext 容器汞斧。
創(chuàng)建 Spring 容器后夜郁,就可以獲取 Spring 容器中的 Beano Spring 獲取 Bean 的實例通常采 用以下兩種方法。
? Object getBean(String name): 根據(jù)容器中 Bean 的 id 或 name 來獲取指定的 Bean 粘勒,獲 取之后需要進行強制類型轉(zhuǎn)換竞端。
? <T> T getBean(Class<T> requiredType) : 根據(jù)類的類型來獲取 Bean 的實例。 由于此方 法為泛型方法庙睡,因此在獲取 Bean 之后不需要進行強制類型轉(zhuǎn)換事富。

  • 小提示
    BeanFactory 和 ApplicationContext 兩種容器都是通過 XML 配置文件加載 Bean 的。 二者的主 要區(qū)別在于埃撵,如果 Bean 的某一個屬性沒有注入赵颅,使用 BeanFacotry JJn載后,在第一次調(diào)用 getBean()方法時會拋出異常暂刘,而 ApplicationContext 則在初始化時自檢饺谬,這樣有利于檢查所依賴 屬性是否注入。 因此 谣拣,在實際開發(fā)中募寨,通常都優(yōu)先選擇使用 ApplicationContext ,而只有在系統(tǒng) 資源較少時森缠,才考慮使用 BeanFactory拔鹰。
Spring的入門程序

通過上一小節(jié)的學習,相信讀者對Spring的核心容器已經(jīng)有了一個初步的了解贵涵。為了幫助大家快速地學習Spring列肢,下面通過一個簡單的入門程序來演示Spring框架的使用。

  • (1)在Eclipse中宾茂,創(chuàng)建一個名為spring01的Web項目瓷马,將Spring的4個基礎(chǔ)包以及commons-Iogging的JAR包復(fù)制到lib目錄中,并發(fā)布到類路徑下跨晴,如下圖所示欧聘。


  • (2)在src目錄,創(chuàng)建一個com.neuedu.ioc包端盆,并在包中創(chuàng)建接口UserDao怀骤,然后在接口中定義一個say()方法,如下面文件所示焕妙。
package com.neuedu.ioc;

public interface UserDao {
  public void say(); 

}
  • (3)在com.neuedu.ioc包下蒋伦,創(chuàng)建UserDao接口的實現(xiàn)類UserDaolmpl,該類需要實現(xiàn)接口中的say()方法焚鹊,并在方法中編寫一條輸出語句凉敲,如下面文件所示。
package com.neuedu.ioc;

public class UserDaoImpl implements UserDao {

  @Override
  public void say() {
      System.out.println("userDao say hello World !");
  }
}
  • (4)在src目錄下,創(chuàng)建Spring的配置文件applicationContext.xml爷抓,并在配置文件中創(chuàng)建一個id為userDao的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"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
   <!-- 將指定類配置給 Spring蓝撇,讓 Spring 創(chuàng)建其對象的實例 --> 
   <bean id="userDao" class="com.neuedu.ioc.UserDaoImpl"></bean>
   
</beans>

在上述文件中果复,第2-5行代碼是Spring的約束配置。該配置信息不需要大家手寫渤昌,可以在Spring的幫助文檔中找到參見本節(jié)中的多學一招)虽抄。第7行代碼表示在Spring器中創(chuàng)建一個id為userDao的Bean實例,其中class屬性用于指定需要實例化Bean的類独柑。
注意:Spring配置文件的名稱可以自定義迈窟,通常在實際開發(fā)中,applicationContext.xml(有時也會命名為beans.xml)忌栅。

  • (5)在com.neuedu.ioc包下车酣,創(chuàng)建測試類TestloC,并在類中編寫main()方法索绪。在main()方法中湖员,需要初始化Spring容器,并加載配置文件瑞驱,然后通過Spring容器獲取userDao實例(即Java對象)娘摔,最后調(diào)用實例中的say()方法,如下面文件所示唤反。
package com.neuedu.ioc;

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

public class TestIoc {
  
  public static void main(String[] args) {
      //1.初始化 spring 容器凳寺,加載配置文件 
      ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
      //2.通過容器獲取 userDao 實例 
      UserDao userDao = (UserDao) applicationContext.getBean("userDao"); 
      //3.調(diào)用實例巾的 say()方法 
      userDao.say();

  }

}

行程序后,控制臺的輸出結(jié)果如下圖所示彤侍。


從圖上圖可以看出读第,控制臺已成功輸出了UserDaolmpl類中的輸出語句。在上面的文件main()方法中拥刻,并沒有通過new關(guān)鍵字來創(chuàng)建UserDao接口的實現(xiàn)類對象,而是通過Spring容器來獲取的實現(xiàn)類對象父泳,這就是SpringloC容器的工作機制般哼。
多學一招:快速獲取配置文件的約束信息
在Spring的配直文件中,包含了很多約束信息惠窄,初學者如果自己動手去編寫蒸眠,不但浪費時間,還容易出錯杆融。其實楞卡,在Spring的幫助文檔中,就可以找到這些約束信息,具體的獲取方法下蒋腮。
打開Spring解壓文件夾中的docs目錄淘捡,在spring-framework-reference文件夾下打開html文件夫,并找到index.html文件池摧,如下圖所示焦除。

使用瀏覽器打開index.html后,在瀏覽器頁面的OverviewofSpringFramework下的7.2.1小節(jié)Configurationmetadata中作彤,即可找到配直文件的約束信息膘魄,如圖所示.在圖中,標記處的配直信息就是Spring配直文件的約束信息竭讳。初學者只需將標注處的信息復(fù)制到項目的配直文件中使用即可创葡。此外,由于使用的是Spring4.3版本绢慢,所以還需要在復(fù)制后的xsd信息中加入版本號信息灿渴,其代碼如下所示。

http://www.springframework.org/schema/beans/spring-beans-4.3.xsd

學習時呐芥,大家可以直接復(fù)制相關(guān)的源代碼逻杖。如果涉及配直文件的約束信息,可以將相應(yīng)源代碼中的配直文件約束信息復(fù)制過來直接使用思瘟。


依賴注入
  • 依賴注入的概念

依賴注入(DependencyInjection荸百,簡稱DI)與控制反轉(zhuǎn)(loC)的含義相同,只不過這兩個稱呼是從兩個角度描述的同一個概念滨攻。對于一個Spring初學者來說十嘿,這兩種稱呼很難理解,下面我們將通過簡單的語言來描述這兩個概念锣吼。當某個Java對象(調(diào)用者)需要調(diào)用另一個Java對象(被調(diào)用者募狂,即被依賴對象)時,在傳統(tǒng)模式下诞帐,調(diào)用者通常會采用"new被調(diào)用者"的代碼方式來創(chuàng)建對象欣尼,如下圖所示。這種方式會導(dǎo)致調(diào)用者與被調(diào)用者之間的捐合性增加停蕉,不利于后期項目的升級和維護愕鼓。



在使用Spring框架之后,對象的實例不再由調(diào)用者來創(chuàng)建慧起,而是由Spring容器來創(chuàng)建菇晃,Spring容器會負責控制程序之間的關(guān)系,而不是由調(diào)用者的程序代碼直接控制蚓挤。這樣磺送,控制權(quán)由應(yīng)用代碼轉(zhuǎn)移到了Spring容器驻子,控制權(quán)發(fā)生了反轉(zhuǎn),這就是Spring的控制反轉(zhuǎn)估灿。
從Spring容器的角度看崇呵,Spring容器負責將被依賴對象賦值給調(diào)用者的成員變量,這相當于為調(diào)用者注入了它依賴的實例甲捏,這就是Spring的依賴注入演熟,如下圖所示。


  • 依賴注入的實現(xiàn)方式

依賴注入的作用就是在使用Spring框架創(chuàng)建對象時司顿,動態(tài)地將其所依賴的對象注入Bean組件中芒粹,其實現(xiàn)方式通常有兩種,一種是屬性setter方法注入大溜,另一種是構(gòu)造方法注入化漆,具體介紹如下。

  • 屬性setter方法注入:指loC容器使用setter方法注入被依賴的實例钦奋。通過調(diào)用無參構(gòu)造器或無參靜態(tài)工廠方法實例化Bean后座云,調(diào)用該Bean的setter方法,即可實現(xiàn)基于setter方法的依賴注入付材。
  • 構(gòu)造方法注入:指loC容器使用構(gòu)造方法注入被依賴的實例朦拖。基于構(gòu)造方法的依賴注入通過調(diào)用帶參數(shù)的構(gòu)造方法來實現(xiàn)厌衔,每個參數(shù)代表著一個依賴璧帝。

了解了兩種注入方式后,下面以屬性setter方法注入的方式為例富寿,講解一下Spring容器在應(yīng)用中是如何實現(xiàn)依賴注入的睬隶。
(1)在com.neuedu.ioc包中,創(chuàng)建接口UserService页徐,在接口中編寫一個say()方法苏潜,如下面文件所示。

package com.neuedu.ioc;

public interface UserService {

  public void say();
}

(2)在com.neuedu.ioc包中变勇,創(chuàng)建UserService接口的實現(xiàn)類UserServicelmpl恤左,在類中聲明userDao屬性,并添加屬性的setter方法搀绣,如下面文件所示飞袋。

package com.neuedu.ioc;

public class UserServicelmpl implements UserService {
  //聲明userDao屬性
  private UserDao userDao;
  //添加屬性的setter方法
  public void setUserDao(UserDao userDao) {
      this.userDao = userDao;
  }
  
  //實現(xiàn)的接口中的方法
  @Override
  public void say() {
      //調(diào)用UserDao中的say()方法,并執(zhí)行輸出語句
      this.userDao.say();
      System.out.println("userService say hello World !");

  }

}

(3)在配置文件appIicationContext.xmI中豌熄,創(chuàng)建一個id為userService的Bean,該Bean用于實例化UserServicelmpl類的信息物咳,并將userDao的實例注入到userService中锣险,其代碼如下所示蹄皱。

<!-- 添加一個 id 為 userService 的實例 --> 
   <bean id="userService" class="com.neuedu.ioc.UserDaoImpl">
      <!-- 將 id 為 userDao 的 Bean 實例注入到 userService 實例中 -->
      <property name="userDao" ref="userDao"></property>
   </bean>

上述代碼中,<property>是<bean>元素的子元素芯肤,它用于調(diào)用Bean實例中的setUserDao()方法完成屬性賦值巷折,從而實現(xiàn)依賴注入。其name屬性表示Bean實例中的相應(yīng)屬性名崖咨,ref屬性用于指定其屬性值锻拘。
(4)在com.neuedu.ioc包中,創(chuàng)建測試類TestDI击蹲,來對程序進行測試署拟,編輯后如下面文件所示。

package com.neuedu.ioc;

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

public class TestDI {

  public static void main(String[] args) {
      //1.初始化 spring 容器歌豺,加載配置文件
      ApplicationContext applicationContext =  new ClassPathXmlApplicationContext("applicationContext.xml"); 
      //2.通過容器獲取 UserService 實例 
      UserService userService = (UserService)applicationContext.getBean("userService"); 
      //3. 調(diào)用實例中的 say() 方法 1
      userService.say();

  }

}

(5)執(zhí)行程序后推穷,控制臺的輸出結(jié)果如圖所示。



從上圖可以看出类咧,使用Spring容器通過UserService實現(xiàn)類中的say()方法馒铃,調(diào)用了UserDao實現(xiàn)類中的say()方法,并輸出了結(jié)果痕惋。這就是Spring容器屬性setter注入的方式区宇,也是實際開發(fā)中最為常用的一種方式。

  • 本章小結(jié)

本章主要講解了Spring框架入門的一些基礎(chǔ)知識值戳。首先講解了Spring框架的概念议谷、作用、優(yōu)點述寡、體系結(jié)構(gòu)以及如何下載和下載后的目錄結(jié)構(gòu)柿隙,然后介紹了Spring的兩種核心容器。接下來通過一個入門程序來講解如何使用Spring框架鲫凶。最后詳細講解了依賴注入和控制反轉(zhuǎn)的概念禀崖,并演示了依賴注入中setter方法注入的實現(xiàn)。通過本章的學習螟炫,大家可以對Spring框架及其體結(jié)構(gòu)有一個初步的了解波附,能夠初步地掌握Spring框架的使用,并能夠理Spring框架中l(wèi)oC和DI的思想昼钻,掌握屬性setter方法注入的實現(xiàn)掸屡。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市然评,隨后出現(xiàn)的幾起案子仅财,更是在濱河造成了極大的恐慌,老刑警劉巖碗淌,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盏求,死亡現(xiàn)場離奇詭異抖锥,居然都是意外死亡,警方通過查閱死者的電腦和手機碎罚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進店門磅废,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人荆烈,你說我怎么就攤上這事拯勉。” “怎么了憔购?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵宫峦,是天一觀的道長。 經(jīng)常有香客問我倦始,道長斗遏,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任鞋邑,我火速辦了婚禮诵次,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘枚碗。我一直安慰自己逾一,他們只是感情好,可當我...
    茶點故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布肮雨。 她就那樣靜靜地躺著遵堵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪怨规。 梳的紋絲不亂的頭發(fā)上陌宿,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天,我揣著相機與錄音波丰,去河邊找鬼壳坪。 笑死,一個胖子當著我的面吹牛掰烟,可吹牛的內(nèi)容都是我干的爽蝴。 我是一名探鬼主播,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼纫骑,長吁一口氣:“原來是場噩夢啊……” “哼蝎亚!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起先馆,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤发框,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后煤墙,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體梅惯,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡顾患,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了个唧。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡设预,死狀恐怖徙歼,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情鳖枕,我是刑警寧澤魄梯,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站宾符,受9級特大地震影響酿秸,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜魏烫,卻給世界環(huán)境...
    茶點故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一辣苏、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧哄褒,春花似錦稀蟋、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至链嘀,卻和暖如春萌狂,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背怀泊。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工茫藏, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人包个。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓刷允,卻偏偏與公主長得像,于是被迫代替她去往敵國和親碧囊。 傳聞我的和親對象是個殘疾皇子树灶,可洞房花燭夜當晚...
    茶點故事閱讀 45,691評論 2 361

推薦閱讀更多精彩內(nèi)容