1. 程式人生 > 實用技巧 >Spring的基本應用

Spring的基本應用

學習目標

  • 掌握:ApplicationContext 容器使用屬性 setter 方法注入的實現
  • 熟悉:Spring 中的 IoC 和 DI
  • 瞭解:Spring 的概念和優點

主要內容

1.1 Spring 概述
1.2 Spring 的核心容器
1.3 Spring 的入門程式
1.4 依賴注入

1.1.1 什麼是 Spring

Spring 是分層的 JavaSE/EE full-stack 輕量級開源框架,以 IoC(Inverse of Control 控制反轉)和 AOP(Aspect Oriented Programming 面向切面程式設計)為核心,使用基本的 JavaBean 來完成以前只可能由 EJB 完成的工作,取代了 EJB 的臃腫、低效的開發模式。

在實際開發中,通常伺服器端在採用三層體系架構,分別為表示層 (Web)、業務邏輯層 (Service)、持久層 (Dao), Spring 對每一層都提供了技術支援。

  • 表示層 在表示層提供了與 Struts 等框架的整合
  • 業務邏輯層 在業務邏輯層可以管理事務、記錄日誌等
  • 持久層 在持久層可以整合 Hibernate、JdbcTemplate
    等技術

1.1.2 Spring 框架的優點

Spring 具有簡單、可測試和鬆耦合等特點。Spring 不僅可以用於伺服器端開發,也可以應用於任何 Java 應用的開發中。

Spring 框架的 7 大優點:

  • 非侵入式設計
  • 方便解耦、簡化開發
  • 支援 AOP
  • 支援宣告式事務處理
  • 方便程式測試
  • 方便整合各種優秀框架
  • 降低 Java EE API 的使用難度

1.1.3 Spring 的體系結構

Spring 框架採用的是分層架構,它一系列的功能要素被分成 20 個模組。

1.1.4 Spring 的下載及目錄結構

Spring 框架包

下載 後的解壓:

  • libs 資料夾中包含 JAR 包和原始碼
  • docs 資料夾中包含 API 文件和開發規範
  • Schema 資料夾中包含開發所需要的 schema 檔案

開啟 libs 目錄可以看到 60 個 JAR 檔案,具體如下:

  • 以 RELEASE.jar 結尾的是 class 檔案 JAR 包
  • 以 RELEASE-javadoc.jar 結尾的是 API 文件壓縮包
  • 以 RELEASE-sources.jar 結尾的是原始檔壓縮包

在 libs 目錄中有四個 Spring 的基礎包,分別對應 Spring 核心容器的四個模組。

  1. spring-core-4.3.6.RELEASE.jar 包含 Spring 框架的核心工具類,Spring 其它元件都要用到這個包裡的類。
  2. spring-beans-4.3.6.RELEASE.jar 所有應用都要用到的 JAR 包,它包含訪問配置檔案、建立和管理 Bean 以及進行控制反轉或者依賴注入操作相關的所有類。
  3. spring-context-4.3.6.RELEASE.jar 提供了在基礎 IoC 功能上的擴充套件服務,還提供了許多企業級服務的支援
  4. spring-expression-4.3.6.RELEASE.jar 定義了 Spring 的表示式語言。

第三方依賴包

在使用 Spring 開發時,除了要使用自帶的 JAR 包外,Spring 的核心容器還需要依賴 commons.logging 的 JAR 包。下載

1.2 Spring 的核心容器

Spring 容器會負責控制程式之間的關係,而不是由程式程式碼直接控制。Spring 為我們提供了兩種核心容器,分別為 BeanFactoryApplicationContext,本節將對這兩種核心容器進行簡單介紹。

1.2.1 BeanFactory

建立 BeanFactory 例項時,需要提供 Spring 所管理容器的詳細配置資訊,這些資訊通常採用 XML 檔案形式來管理,其載入配置資訊的語法如下:

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

這種載入方式在實際開發中並不多用,作為了解即可。

1.2.2 ApplicationContext

ApplicationContextBeanFactory 的子介面,是另一種常用的 Spring 核心容器。它由 org.springframework.context.ApplicationContext 介面定義,不僅包含了 BeanFactory 的所有功能,還添加了對國際化、資源訪問、事件傳播等方面的支援。建立 ApplicationContext 介面例項,通常採用兩種方法,具體如下:

  1. 通過 ClassPathXmlApplicationContext 建立
ApplicationContext applicationContext =
  new ClassPathXmlApplicationContext(String configLocation);

ClassPathXmlApplicationContext 會從類路徑 classPath 中尋找指定的 XML 配置檔案,找到並裝載完成 ApplicationContext 的例項化工作。

  1. 通過 FileSystemXmlApplicationContext 建立
ApplicationContext applicationContext =
  new FileSystemXmlApplicationContext(String configLocation);

FileSystemXmlApplicationContext 會從指定的檔案系統路徑(絕對路徑)中尋找指定的 XML 配置檔案,找到並裝載完成 ApplicationContext 的例項化工作。


在 Java 專案中,會通過 ClassPathXmlApplicationContext 類來例項化 ApplicationContext 容器。而在 Web 專案中,ApplicationContext 容器的例項化工作會交由 Web 伺服器來完成。

Web 伺服器例項化 ApplicationContext 容器時,通常會使用 ContextLoaderListener 來實現,此種方式只需要在 web.xml 中新增如下程式碼:

<context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
                  classpath:spring/applicationContext.xml
        </param-value>
</context-param>
<listener>
        <listener-class>
                  org.springframework.web.context.ContextLoaderListener
        </listener-class>
</listener>

1.3 Spring 的入門程式

  1. 在 Eclipse 中,建立一個名為 chapter01 的 Web 專案,將 Spring 的 4 個基礎包以及 commons-logging 的 JAR 包複製到 lib 目錄中,併發布到類路徑下。

  2. 在 src 目錄下,建立一個 com.itheima.ioc 包,並在包中建立介面 UserDao,然後在介面中定義一個 say() 方法。

package com.itheima.ioc;
public interface UserDao {
   	public void say();
}
  1. 在 com.itheima.ioc 包下,建立 UserDao 介面的實現類 UserDaoImpl,該類需要實現介面中的 say() 方法,並在方法中編寫一條輸出語句。
package com.itheima.ioc;
public class UserDaoImpl implements UserDao {
  public void say() {
          System.out.println("userDao say hello World !");
  }
}
  1. 在 src 目錄下,建立 Spring 的配置檔案 applicationContext.xml,並在配置檔案中建立一個 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">
      <bean id="userDao" class="com.itheima.ioc.UserDaoImpl" />
</beans>
  1. 在 com.itheima.ioc 包下,建立測試類 TestIoC,並在類中編寫 main() 方法。在 main() 方法中,需要初始化 Spring 容器,並載入配置檔案,然後通過 Spring 容器獲取 userDao 例項(即 Java 物件),最後呼叫例項中的 say() 方法。
package com.itheima.ioc;
import org.springframework.context.ApplicationContext;
import  org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestIoC {
  public static void main(String[] args) {
    ApplicationContext applicationContext =
    new ClassPathXmlApplicationContext("applicationContext.xml");
    UserDao userDao = (UserDao) applicationContext.getBean("userDao");
    userDao.say();
  }
}

控制檯 Console:

userDao say hello World !

1.4.1 依賴注入的概念

什麼是依賴?

如果類 A 的物件要完成某一操作,必須呼叫類 B 的物件的某些操作來幫忙,才能完成。我們稱作類 A 依賴類 B。
舉例:a 物件呼叫 b 物件的 x() 方法,完成 a 物件的 y() 方法。

對於依賴關係通常解決方法:

public class B {
public void x() {
  System.out.println("b.x()  is called!--common");
}

對於依賴關係通常解決方法:

public class A {
	private B b;
	public void setB(B b) {
		this.b=b;
	}
	public void y() {
		b.x();
		System.out.println("a.y()  is called!--common");
	}
}

對於依賴關係通常解決方法:

public class TestNoSpringCommon {
	public static void main(String[] args) {
		A a=new A();            // 新建物件 a
		B b=new B();            // 新建物件 b
		a.setB(b);              // 呼叫物件 a.setB(b) 方法
		a.y();                  // 呼叫物件 a.y() 方法
	}
}

對於依賴關係(介面方式)通常解決方法:

public interface BInterface {
	public void x();
}

public class BImpl implements BInterface{
	public void x() {
		System.out.println("b.x() is called!--noSpringUseInterface");
	}
}

對於依賴關係(介面方式)通常解決方法:


public interface AInterface {
	public void y();
}

public class AImpl implements AInterface{
	private BImpl b;
	public void setB(BImpl b) {
		this.b=b;
	}
	public void y() {
		b.x();
		System.out.println("a.y() is called!--noSpringUseInterface");
	}
}

對於依賴關係(介面方式)通常解決方法:

public class TestNoSpring {
	public static void main(String[] args) {
		AImpl aImpl=new AImpl();
		BImpl bImpl=new BImpl();
		aImpl.setB(bImpl);
		aImpl.y();
	}
}

DI 的全稱是 Dependency Injection,中文稱之為依賴注入。它與控制反轉(IoC:Inversion of Control)的含義相同,只不過這兩個稱呼是從兩個角度描述的同一個概念。

IoC

在使用 Spring 框架之後,物件的例項不再由應用程式使用 new 來建立,而是由 Spring 容器來建立,Spring 容器會負責控制程式之間的關係,而不是由應用程式程式碼直接控制。這樣,控制權由應用程式碼轉移到了 Spring 容器,控制權發生了反轉,這就是控制反轉。

DI

從 Spring 容器的角度來看,Spring 容器負責將被依賴物件賦值給呼叫者的成員變數,這相當於為呼叫者被注入了它依賴的例項,這就是 Spring 的依賴注入。

對於依賴關係(介面方式)使用 Spring 解決方法:

提前引入使用 spring 框架的基礎 jar 檔案:4+1

public interface BInterface {
	public void x();
}

public class BImpl implements BInterface{
	public void x() {
		System.out.println("b.x() is called!--useSpring");
	}
}
public interface AInterface {
	public void y();
}

public class AImpl implements AInterface{
	private BImpl b;
	public void setB(BImpl b) {
		this.b=b;
	}
	public void y() {
		b.x();
		System.out.println("a.y() is called!--useSpring");
	}
}
public class TestDI {
	public static void main(String[] args) {
    ApplicationContext applicationContext = 
      new ClassPathXmlApplicationContext("applicationContext.xml"); //初始化 spring 容器,載入配置檔案
    AImpl aImpl = (AImpl) applicationContext.getBean("aImpl"); //通過容器獲取 aImpl 例項
    aImpl.y();     //呼叫 aImpl.y() 方法
	}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans>
    <!--新增一個 id 為 bImpl 的 springdi.BImpl 的例項 -->
    <bean id="bImpl" class="springdi.BImpl" />
	 <!--新增一個 id 為 aImpl 的 springdi.AImpl 的例項 -->
	 <bean id="aImpl" class="springdi.AImpl">
	 <!-- 將 id 為 bImpl 的 Bean 例項注入到 springdi.AImpl 例項中 -->
		  <property name="b" ref="bImpl" />
	 </bean>
</beans>

1.4.2 依賴注入的實現

  1. 在 com.itheima.ioc 包中,建立介面 UserService,在介面中編寫一個 say() 方法。
package com.itheima.ioc;
public interface UserService {
          public void say();
}
  1. 在 com.itheima.ioc 包中,建立 UserService 介面的實現類 UserServiceImpl,在類中宣告 userDao 屬性,並新增屬性的 setter 方法。
package com.itheima.ioc;
public class UserServiceImpl implements UserService {
  private UserDao userDao;
  public void setUserDao(UserDao userDao) {
    this.userDao = userDao;
  }
  public void say() {
    this.userDao.say();
    System.out.println("userService say hello World !");
  }
}
  1. 在配置檔案 applicationContext.xml 中,建立一個 id 為 userService 的 Bean,該 Bean 用於例項化 UserServiceImpl 類的資訊,並將 userDao 的例項注入到 userService 中。
<bean id="userService" class="com.itheima.ioc.UserServiceImpl">
  <property name="userDao" ref="userDao" />
</bean>
  1. 在 com.itheima.ioc 包中,建立測試類 TestDI,來對程式進行測試。
package com.itheima.ioc;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestDI {
  public static void main(String[] args) {
    ApplicationContext applicationContext =
      new ClassPathXmlApplicationContext("applicationContext.xml");
    UserService userService =
      (UserService) applicationContext.getBean("userService");
    userService.say();
  }
}
  1. 控制檯 Console:
userDao say hello World !
userService say hello World !

小結

本章主要介紹了 Spring 框架入門的一些基礎知識,包括 Spring 的概念、優點、體系結構、核心容器、依賴注入等,同時通過一個入門程式講解了 Spring 的基本使用。

通過本章的學習,讀者可以對 Spring 框架及其體系結構有一個初步的瞭解,能夠初步的掌握 Spring 框架的使用,並能夠理 Spring 框架中 IoC 和 DI 的思想,掌握屬性 setter 方法注入的實現。

本章作業

請簡述 Spring 框架的優點。
請簡述什麼是 Spring 的 IoC 和 DI。