天天看點

Java單體應用 - 常用架構 - 02.SpringSpring

原文位址: http://www.work100.net/training/monolithic-frameworks-spring.html 更多教程: 光束雲 - 免費課程

Spring

請參照如上

章節導航

進行閱讀

1.概述

Spring 的主要作用就是為代碼“

解耦

”,降低代碼間的耦合度。

根據功能的不同,可以将一個系統中的代碼分為 主業務邏輯 與 系統級業務邏輯 兩類,它們各自具有鮮明的特點:

  • 主業務代碼間邏輯聯系緊密,有具體的專業業務應用場景,複用性相對較低;
  • 系統級業務相對功能獨立,沒有具體的專業業務應用場景,主要是為主業務提供系統級服務,如日志、安全、事務等,複用性強。

Spring 根據代碼的功能特點,将降低耦合度的方式分為了兩類:

IoC

AOP

  • IoC 使得主業務在互相調用過程中,不用再自己維護關系了,即不用再自己建立要使用的對象了。而是由 Spring 容器統一管理,自動“注入”。
  • 而 AOP 使得系統級服務得到了最大複用,且不用再由程式員手工将系統級服務“混雜”到主業務邏輯中了,而是由 Spring 容器統一完成“織入”。

Spring 是于 2003 年興起的一個輕量級的 Java 開發架構,它是為了解決企業應用開發的複雜性而建立的。

Spring 的核心是控制反轉(IoC)和面向切面程式設計(AOP)。

簡單來說,Spring 是一個分層的 Java SE/EE full-stack(一站式)輕量級開源架構。

2.體系結構

Java單體應用 - 常用架構 - 02.SpringSpring

Spring 由 20 多個子產品組成,它們可以分為資料通路/內建(Data Access/Integration)、Web、面向切面程式設計(AOP, Aspects)、應用伺服器裝置管理(Instrumentation)、消息發送(Messaging)、核心容器(Core Container)和測試(Test)。

3.特點

非侵入式

所謂非侵入式是指,Spring 架構的 API 不會在業務邏輯上出現,即業務邏輯是 POJO。

由于業務邏輯中沒有 Spring 的 API,是以業務邏輯可以從 Spring 架構快速的移植到其他架構, 即與環境無關。

容器

Spring 作為一個容器,可以管理對象的生命周期、對象與對象之間的依賴關系。可以通過配置檔案,來定義對象,以及設定與其他對象的依賴關系。

IoC

控制反轉(Inversion of Control),即建立被調用者的執行個體不是由調用者完成,而是由 Spring 容器完成,并注入調用者。

當應用了 IoC,一個對象依賴的其它對象會通過被動的方式傳遞進來,而不是這個對象自己建立或者查找依賴對象。即,不是對象從容器中查找依賴,而是容器在對象初始化時不等對象請求就主動将依賴傳遞給它。

AOP

面向切面程式設計(AOP,Aspect Orient Programming),是一種程式設計思想,是面向對象程式設計 OOP 的補充。很多架構都實作了對 AOP 程式設計思想的實作。Spring 也提供了面向切面程式設計的豐富支援,允許通過分離應用的業務邏輯與系統級服務(例如日志和事務管理)進行開發。應用對象隻實作它們應該做的——完成業務邏輯——僅此而已。它們并不負責其它的系統級關注點,例如日志或事務支援。

我們可以把日志、安全、事務管理等服務了解成一個“切面”,那麼以前這些服務一直是直接寫在業務邏輯的代碼當中的,這有兩點不好:首先業務邏輯不純淨;其次這些服務被很多業務邏輯反複使用,完全可以剝離出來做到複用。那麼 AOP 就是這些問題的解決方案, 可以把這些服務剝離出來形成一個“切面”,以期複用,然後将“切面”動态的“織入”到業務邏輯中,讓業務邏輯能夠享受到此“切面”的服務。

4.Spring與IoC

控制反轉(IoC,Inversion of Control),是一個概念,是一種思想。指将傳統上由程式代碼直接操控的對象調用權交給容器,通過容器來實作對象的裝配和管理。控制反轉就是對對象控制權的轉移,從程式代碼本身反轉到了外部容器。

IoC 是一個概念,是一種思想,其實作方式多種多樣。目前比較流行的實作方式有兩種: 依賴注入和依賴查找。依賴注入方式應用更為廣泛。

  • 依賴查找:Dependency Lookup,DL,容器提供回調接口和上下文環境給元件,程式代碼則需要提供具體的查找方式。比較典型的是依賴于 JNDI 系統的查找。
  • 依賴注入:Dependency Injection,DI,程式代碼不做定位查詢,這些工作由容器自行完成。

依賴注入 DI 是指程式運作過程中,若需要調用另一個對象協助時,無須在代碼中建立被調用者,而是依賴于外部容器,由外部容器建立後傳遞給程式。

Spring 的依賴注入對調用者與被調用者幾乎沒有任何要求,完全支援 POJO 之間依賴關系的管理。

依賴注入是目前最優秀的解耦方式。依賴注入讓 Spring 的 Bean 之間以配置檔案的方式組織在一起,而不是以寫死的方式耦合在一起的。

5.第一個Spring應用程式

5.1.建構項目結構

建立一個檔案夾為

hello-spring

的項目,然後增加

pom.xml

檔案,代碼如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>net.work100.training.stage2</groupId>
    <artifactId>hello-spring</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>
    </dependencies>
</project>           
增加

org.springframework:spring-context

依賴

然後建構項目結構,并将

pom.xml

檔案托管到

Maven

,如下圖:

Java單體應用 - 常用架構 - 02.SpringSpring

5.2.代碼實作

建立 UserService 接口

UserService.java

檔案代碼如下:

package net.work100.training.stage2.hello.spring.service;

/**
 * <p>Title: UserService</p>
 * <p>Description: </p>
 *
 * @author liuxiaojun
 * @date 2020-02-12 13:32
 * ------------------- History -------------------
 * <date>      <author>       <desc>
 * 2020-02-12   liuxiaojun     初始建立
 * -----------------------------------------------
 */
public interface UserService {
    void sayHi();
}           

建立 UserServiceImpl 實作

UserServiceImpl.java

package net.work100.training.stage2.hello.spring.service.impl;

import net.work100.training.stage2.hello.spring.service.UserService;

/**
 * <p>Title: UserServiceImpl</p>
 * <p>Description: </p>
 *
 * @author liuxiaojun
 * @date 2020-02-12 13:32
 * ------------------- History -------------------
 * <date>      <author>       <desc>
 * 2020-02-12   liuxiaojun     初始建立
 * -----------------------------------------------
 */
public class UserServiceImpl implements UserService {
    public void sayHi() {
        System.out.println("Hello Spring");
    }
}           

5.3.配置 Spring

src/main/resources

目錄下建立

spring-context.xml

配置檔案,從現在開始類的執行個體化工作交給 Spring 容器管理(IoC),配置檔案如下:

<?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 id="userService" class="net.work100.training.stage2.hello.spring.service.impl.UserServiceImpl" />
</beans>           

5.4.測試 Spring IOC

建立一個 MyTest 測試類,測試對象是否能夠通過 Spring 來建立,代碼如下:

package net.work100.training.stage2.hello.spring;

import net.work100.training.stage2.hello.spring.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * <p>Title: MyTest</p>
 * <p>Description: </p>
 *
 * @author liuxiaojun
 * @date 2020-02-12 13:35
 * ------------------- History -------------------
 * <date>      <author>       <desc>
 * 2020-02-12   liuxiaojun     初始建立
 * -----------------------------------------------
 */
public class MyTest {
    public static void main(String[] args) {
        // 擷取 Spring 容器
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-context.xml");

        // 從 Spring 容器中擷取對象
        UserService userService = (UserService)applicationContext.getBean("userService");
        userService.sayHi();
    }
}           

5.5.運作

運作結果如下:

Hello Spring           

5.6.源碼擷取

執行個體源碼已經托管到如下位址:

上一篇:

Bootstrap

下一篇:

JUnit
如果對課程内容感興趣,可以掃碼關注我們的

公衆号

QQ群

,及時關注我們的課程更新
Java單體應用 - 常用架構 - 02.SpringSpring
Java單體應用 - 常用架構 - 02.SpringSpring

繼續閱讀