Spring入門筆記簡要

醉千燈發表於2022-03-10

總覽:https://www.processon.com/view/link/605b14ab5653bb2225e6b0c5

一、Spring

1、概述

1、spring框架簡介

​ 為簡化企業級開發而生,有效的降低程式碼的耦合度,極大的方便專案的後期維護、升級和擴充套件。

2、優點

​ 輕量、AOP支援、支援對各種框架的整合

3、體系結構

1、資料訪問

2、Web開發

3、AOP

4、整合訊息等

5、核心容器 IOC

2、IOC控制反轉

​ ioc(Inversion of Control)是一種設計思想,把物件的建立、賦值、管理工作都交給程式碼之外的容器實現,也就是物件的建立是有其他外部資源完成。

控制:建立物件,物件賦值,物件之間的關係管理

反轉:把原來開發人員管理、建立物件的許可權轉交給程式碼之外的容器實現,由容器代替開發人員管理物件,建立、賦值等

正轉:由開發人員在程式碼中,使用new構造方法建立物件,開發人員主動管理物件‘;

容器:是一個伺服器軟體(Tomcat),一個框架(spring)等

目的:

減少對程式碼的改動,也能實現不同的功能,實現解耦合

所以:java中建立物件的方式:

1、new

2、反射,class的newInstance()方法,constructor的newInstance()方法

3、反序列化

4、克隆

5、ioc

ioc的技術實現:

​ DI 是 ioc 的技術實現

​ DI (Dependency Injection)依賴注入:只需要在程式中提供使用的物件名稱就可以,至於物件如何在容器中建立、賦值、查詢都由容器內部實現。

spring是使用的 DI 實現了 ioc 的功能,spring底層建立物件,使用的是反射機制。

2.1 由spring建立物件

實現步驟:
  1. 建立maven專案

  2. 加入maven依賴

    ​ spring依賴、junit依賴

  3. 建立類(介面和他的實現類)

    ​ 和沒有使用框架一樣,就是普通類

  4. 建立spring需要使用的配置檔案

    ​ 宣告類的資訊,由spring建立和管理

僅限於初學的寫法:

2.2 DI(依賴注入)的實現方式:

1、基於xml配置檔案:在Spring配置檔案中,使用標籤和屬性完成

2、基於註解的實現:使用spring中的註解,完成屬性賦值

2.2.1 基於xml配置檔案

​ 適合經常需要修改

DI的語法分類:

1、 注入(set設值, 注入就是賦值):spring呼叫類的set方法,在set方法中實現屬性的賦值(最常用)

2、構造注入,spring呼叫類的有參構造方法,建立物件,在構造方法中完成賦值

set注入:

  1. 簡單型別的set注入:

property設值時name屬性必須在相應的類中有set方法,且有set方法沒有相應的變數也不會報錯

​ 2.引用型別的set注入:

​ 引用型別的自動注入:

​ 1、byName:java類中引用型別的屬性名和spring容器中(配置檔案)的id名稱一樣,且資料型別一致,這樣的容器中的bean,spring能夠賦值給引用型別

<bean id="xx" class="yy" autowire="byName"></bean>

讓Student類中所有的引用型別都按照byName規則完成賦值

​ 2、byType(按型別注入):java類中引用型別的資料型別和spring容器中(配置檔案)的class屬性是同源關係的,這樣的bean能夠賦值給引用型別

​ 同源:1、java類中引用型別的資料型別和bean中的class值一樣

​ 2、java類中引用型別的資料型別和bean中的class值父子類關係的

​ 3、java類中引用型別的資料型別和bean中的class值介面和實現類關係的

​ 注:只能有一個符合條件的,多個會報錯

​ class是Student類中引用的School的值:

構造注入

name屬性實現構造注入

index屬性實現

可以省略index=“”,但是必須按照引數的定義順序書寫

多配置檔案優勢:

  1. 每個檔案的大小比一個檔案小很多,效率高

  2. 避免多人競爭帶來的衝突

    按檔案的分配方式:

  3. 按功能模組,一個模組一個配置檔案

  4. 按類的功能,資料庫相關的配置一個配置檔案,做事務的功能一個配置檔案,做service功能的一個配置檔案

2.2.2 基於註解的實現

​ 快捷,方便,適合不經常修改的

實現步驟:

  1. 加入maven依賴spring-context(間接加入了spring-aop依賴)

  2. 建立類,在類中加入spring 註解@Component(value=“xxx”),省略value=也可以(常用),如果只寫@Component則會預設value=首字母小寫的類名

    還有
    @Repository(用在持久層):放在dao的實現類,表示建立dao物件,dao物件是能訪問資料庫的
    @Service(用在業務層):service物件是做業務處理,可以有事務等功能的
    @Controller(用在控制器上):放在控制器(處理器)類的上面,建立控制器物件的,控制器物件能夠接受使用者提交的引數,顯示請求的處理結果
    以上三個適用語法和@Component一樣,都能建立物件,但是他們三個還有額外的功能
    
    

    引用型別-@Autowired

    引用型別@Resource

  3. 在spring配置檔案中,加入一個元件掃描器的標籤,說明註解在專案中的位置

    需要指定多個包時:

3、AOP面向切面程式設計

3.1 動態代理

​ 動態代理能建立物件,在原有類程式碼不變的情況下,實現功能的增加,功能增強。

3.1.1 JDK 動態代理

​ 要求目標物件必須實現介面,java語言通過java.lang.reflect包提供三個類支援代理模式Proxy,Method和InvcationHandler,要求目標類和方法不能是final的,因為final不能被繼承,不能被重寫啊

實現步驟:

  1. 建立目標類,SomeserviceImpl目標類,給它的doSome,dother增加輸出時間,事務。

  2. 建立InvocationHandler介面的實現類,在這個類實現給目標方法增加功能。

  3. 使用jdk中類Proxy ,建立代理物件。實現建立物件的能力。

作用:

  1. 在目標類原始碼不改變的情況下,增加功能

  2. 減少程式碼的重複

  3. 專注業務程式碼邏輯

  4. 解耦合,讓業務與日誌扥,事務非業務功能分離

3.1.2 CGLB動態代理(瞭解)

​ CDLIB(Code Generation Library)是一個開源專案,原理是生成目標類的子類,子類是代理物件。

3.2 AOP簡介

AOP(Aspect Orient Programming) 面向切面程式設計,底層的實現就是採用動態代理模式實現的,採用了JDK的動態代理和CGLIB的動態代理。

Aspect:切面,給目標類增加的功能

​ 特點:一般都是非業務方法,獨立使用的

如何理解AOP:

​ 以切面為核心,圍繞切面來開發程式:

​ 1)分析專案功能時找到切面

​ 2)合理安排執行時間,(在目標方法前還是後)

​ 3)合理的安排切面執行的位置, 在哪個類,哪個方法增加增強功能

3.3 AOP程式設計術語

  1. AOP:切面,表示增強的功能,就是一堆程式碼,完成某一個功能,非業務功能

    ​ 常見的切面功能有日誌,事務,統計資訊,引數檢查,許可權驗證

  2. JoinPoint:連線點,連線業務方法和切面的位置,就是某類中的業務方法

  3. PointCut:切入點,指多個連線方法的集合,多個方法

  4. 目標物件:給哪個類的方法這個價功能,這個類就是目標物件

  5. Advice:通知,表示切面功能 執行的時間,方法之前還是之後

切面三個關鍵要素:

  1. 切面的功能程式碼,切面幹什麼
  2. 切面的執行位置,使用PointCut表示切面執行的位置
  3. 切面的執行時間,使用Advice表示時間,在目標方法之前還是之後

3.4 AOP的實現

​ AOP是一個規範,是動態的一個規範化,一個標準

​ aop的技術實現框架:

  1. spring:spring內部實現了aop的規範,能做aop的工作

    ​ spring在處理事務時使用aop

    ​ 在專案開發中很少使用spring的aop實現,因為spring的aop比較笨重

  2. Aspect:一個開源的專門做aop的框架,spring框架中整合了aspectj框架,通過spring就能使用aspectj的功能

    aspectj框架實現aop的兩種方式:

    1. 使用xml的配置檔案:配置全域性事務
    2. 使用註解,在專案中要做aop功能,一般使用註解

3.4 AspectJ框架的使用

  1. 切面的執行時間,這個執行時間在規範中叫做Advice(通知,增強)

    在aspect框架中使用註解表示,也可以使用xml配置檔案中的標籤

    <!-- 5個常用註解
    @Before
    @AfterReturning
    @Around
    @After
    @AfterThrowing
    -->
    
  2. 表示切面執行的位置,使用的是切入表示式

    execution(訪問許可權 方法返回值 方法引數 異常型別)

    在其中可以使用以下符號:
    *	:0至多個任意字元
    ..	: 用在方法引數中,表示任意多個引數;用在包名後,表示當前包及其子包
    +	:用在類名後,表示當前類及其子類;用在介面名後,表示當前介面及其實現類
    
    指定切入點為:任意公共方法
    execution(public * *(..))
    指定切入點為:任意一個以set開始的方法
    execution(* set*(..))
    指定切入點為:com.mhz.service包中的任意類中的任意方法,不包含子包
    execution(* com.mhz.service.*.*(..))
    指定切入點為:com.mhz.service或者子包包中的任意類中的任意方法
    execution(* com.mhz.service..*.*(..))
    指定切入點為:所有service包下的任意類的任意方法
    execution(* *..service.*.*(..))
        
    
使用aspectJ實現aop的基本步驟:
  1. 新建maven專案

  2. 加入依賴

    1. spring依賴
    2. aspectj依賴
    3. junit單元測試(可有可無)
  3. 建立目標類:介面和他的實現類

    要做的是給類中的方法增加功能

  4. 建立切面類:普通類

    1. 在類上加入註解@Aspect

    2. 定義方法,方法就是切面要執行的功能程式碼

      ​ 在方法上面加入aspectj中的註解,例如@Before,

      ​ 有需要指定切入點表示式execution()

  5. 建立spring配置檔案:宣告物件,把物件交給容器統一管理

    ​ 宣告物件可以使用xml配置檔案或者註解

    1. 宣告目標物件

    2. 宣告切面類物件

    3. 宣告aspectj框架中的自動代理生成器標籤。

      ​ 自動代理生成器:用來完成代理物件的自動建立功能的。

    <!--把物件交給spring容器,由spring容器統―建立,管理物件-->
    <! --宣告目標物件-->
    <bean id="someservice" class="com.bjpowernode.bao1.SomeserviceImpl"/>
    <! --宣告切面類物件-->
    <bean id="myAspect" class="com.bjpowernode.ba01.MyAspect”/>
    <!--
    宣告自動代理生成器:使用aspectj框架內部的功能,建立目標物件的代理物件。
    建立代理物件是在記憶體中實現的,修改目標物件的記憶體中的結構。建立為代理物件所以目標物件就是被修改後的代理物件
    aspectj-autoproxy:會把spring容器內的所有目標物件,一次性都生成代理物件
                               -->   
    <aop: aspectj-autoproxy />
    
  6. 建立測試類,從spring容器中獲取目標物件(代理物件)

    ​ 通過代理物件實現aop

六個註解:

1、@Before:

前置通知註解
屬性: value,是切入點表示式,表示切面的功能執行的位置。
位置:	在方法的上面
特點:
1.在目標方法之前先執行的
2.不會改變目標方法的執行結果
3.不會影響目標方法的執行。

/*
 * 指定通知方法中的引數:JoinPoint
 * JoinPoint:業務方法,要加入切面功能的業務方法
 * 作用是:可以在通知方法中獲取方法執行時的資訊,例如方法名稱,方法的實參。
 * 如果你的切面  功能中需要用到方法的資訊,就加入JoinPoint.
 * 這個JoinPoint引數的值是由框架賦予,必須是第一個位置的引數
*/

@Before(value = "execution(void *..SomeServiceImpl.doSome(String, Integer))")
public void myBefore(JoinPoint jp){
	//獲取方法的完整定義
	system.out.println("方法的簽名(定義)="+jp.getsignature());
	system.out.println("方法的名稱="+jp.getsignature().getName());//獲取方法的實參
	object args []= jp.getArgs();
	for (object arg:args){
		system.out.println("引數="+arg);
	}
}

2、@AfterReturning:

後置通知定義方法,方法是實現切面功能的。
方法的定義要求:
1.公共方法 public
2.方法沒有返回值
3.方法名稱自定義
4.方法有引數的,推薦是object,引數名自定義

@AfterReturning:後置通知
屬性: 
1.value切入點表示式
2.returning自定義的變數,表示目標方法的返回值的。自定義變數名必須和通知方法的形參名一樣。
位置:在方法定義的上面
特點:
1. 在目標方法之後執行的。
2. 能夠獲取到目標方法的返回值,可以根據這個返回值做不同的處理功能
3. 可以修改這個返回值
@AfterReturning(value="execution(* *..SomeServiceImpl.doOther(..))",returning="res")
// 此處returning的res名稱=Object的res名稱就行
public void myAfterReturing(object res){
	// object res:是目標方法執行後的返回值,根據返回值做你的切面的功能處理
    // 思考:如果是對類物件res的更改會不會影響在程式執行後得到的輸出結果?
	system.out.println("後置通知:在目標方法之後執行的,獲取的返回值是:"+res);
    if(res.equals("abcd"))
    {
		//做―些功能
	}
    e1se
    {
		//做其它功能
	}
    
}

3、@Around

環繞通知
方法的定義格式:
1.public
2.必須有一個返回值,推薦使用object
3.方法名稱自定義
4.方法有引數,固定的引數ProceedingjoinPoint
@Around:環繞通知
屬性:value切入點表示式位宣:在方法的定義什麼
特點:
1.它是功能最強的通知
2.在目標方法的前和後都能增強功能。
3.控制目標方法是否被呼叫執行
4.修改原來的目標方法的執行結果。影響最後的呼叫結果

等同於jdk動態代理的,InvocationHandler介面
引數:ProceedingJoinPoint 等同於Method
		作用:執行目標方法
返回值:就是目標方法的執行結果,可以被修改
@Around(value = "execution(* *..SomeService1mpl.doFirst(..))")
public object myAround(ProceedingJoinPoint pjp) throws Throwable {
	// 獲取第一個引數值
    Object[] args = pjp.getArgs();
    String name = "";
    if(args != null && args.length > 1){
        Object arg = args[0];
        name = (String)arg;
    }
    //實現環繞通知
	object result = null;
	system.out.println("環繞通知:在目標方法之前,輸出時間:"+ new Date());
    //1.目標方法呼叫
    if("xxx".equals(name)){
         // 控制是否執行目標方法
        result = pjp.proceed(); //method.invoke(); object result = doFirst();
    }
    system.out.println("環繞通知:在目標方法之後,提交事務");
	//2.在目標方法的前或者後加入功能
	//返回目標方法的執行結果
	return result;
}

4、 @AfterThrowing

異常通知:
1、public
2、沒有返回值
3、方法,名稱自定義
4、方法有一個Exception,如果還有就是JoinPoint
@AfterThrowing:異常通知
屬性:1、value
	 2、throwing自定義變數,表示目標方法丟擲的異常物件,變數名和方法的引數名一樣
特點:1、在目標方法丟擲異常時執行
	 2、可以做異常的監控程式,如果有異常,可以發郵件,簡訊通知等
執行時:
沒有異常就走正常邏輯,有異常就走定義的@AfterThrowing註解的方法
try{
	SomeServiceImpl.doSecond(..);
}
catch(Exception ex){
	myAfterThrowing(ex);
}
@AfterThrowing(value = "execution(* *..SomeServiceImpl.doSecond(..))",throwing = "ex")
public void myAfterThrowing(Exception ex){
	system.out.println("異常通知:方法發生異常時,執行: "+ex.getMessage());//傳送郵件,簡訊,通知開發人員
}

5、@ After

最終通知
方法的定義格式
1.public
2.沒有返回值
3.方法名稱自定義
4.方法沒有引數,如果還有是JoinPoint
@After:最終通知
	屬性:value 切入點表示式
	位置:方法上面
特點:
	1、總是執行
	2、目標方法後執行,即使丟擲了異常
類似於:
try/catch中的finally程式碼塊
@After(value = "execution(* *..SomeserviceImpl.doThird(..))")
public loidmyAfter(){
    //一般做資源清除工作的。
	systemyout.println("執行最終通知,總是會被執行的程式碼");
}

6、 @PointCut

定義管理切入點
如果專案中很多個切入點表示式是重複的,,使用@PointCut
屬性:value 切入點表示式
位置:方法上面
特點:
	當使用@Pointcut定義在一個方法的上面,此時這個方法的名稱就是切入點表示式的別名。其它的通知中,value屬性就可以使用這個方法名稱,代替切入點表示式了
@Pointcut(value = "execution(* *..SomeserviceImpl.doThird(..))”)
private void mypt(){
	//無需程式碼,
}
// 然後:
@Before(value="mypt()")
public void myBefore(){
    
}

4、Spring事務

4.1 Spring的事務管理

  1. 什麼是事務?

    ​ 指的是一組sql語句的集合,集合中有多個sql語句,增刪查改,希望這些sql語句鬥毆成功或者都失敗,這些sql 的執行是一致的,作為一個整體執行。

  2. 什麼時候用到事務?

    ​ 當操作涉及多個表或者多個sql語句的增刪改,需要保證這些sql語句都成功才能完成功能,或者都失敗,保證操作是符合要求的。

    ​ 在java程式碼中寫程式,控制事務,需要寫在service類的業務方法上,因為業務方法匯呼叫多個dao方法,執行多個sql語句

  3. jdbc、Mybatis訪問資料庫處理事務?

    //jdbc
    Connection conn;
    conn.commit();
    conn.rollback();
    //mybatis
    SqlSession.commit();
    SqlSession.rollback();
    
  4. 問3中處理事務的方式是不同的,所以有哪些不足:

    1. 不同的資料庫訪問技術,處理事務的物件、方法不同,需要掌握瞭解不同資料庫訪問技術使用事務的原理

    2. 掌握多種資料庫中事務的處理邏輯,提交、回滾等

      多種資料庫訪問技術,有不同的事務處理的機制,物件、方法

  5. 解決不足

    ​ spring提供一種統一處理事務的統一模型,能使用統一步驟,方式完成多種不同資料庫訪問技術的事務處理。

    ​ 使用spring的事務處理機制,可以完成mybatis、hibernate等訪問資料庫的事務處理。

  6. 處理事務,需要怎麼做,做什麼
    spring處理事務的模型,使用的步驟都是固定的。把事務使用的資訊提供給spring就可以了

    1. 事務內部提交,回滾事務,使用的事務管理器物件,代替你完成commit,rollback

      事務管理器是一個介面和他的眾多實現類。

      介面:PlatformTransactionManager ,定義了事務重要方法commit , rollback

      實現類: spring把每一種資料庫訪問技術對應的事務處理類都建立好了。
      mybatis訪問資料庫---spring建立好的是DatasourceTransactionManagerhibernate

      ​ 訪問資料庫----spring建立的是HibernateTransactionManager
      怎麼使用:你需要告訴spring 你用是那種資料庫的訪問技術,怎麼告訴spring呢?
      宣告資料庫訪問技術對於的事務管理器實現類,在spring的配置檔案中使用宣告就可以了例如,你要使用mybatis訪問資料庫,你應該在xml配置檔案中

      <bean id="xxx" class=" . ..DataSourceTransactionManager">
      
    2. 業務方法需要什麼樣的事務,說明需要事務的型別。

      ​ 說明方法需要的事務:

      ​ 1)事務的隔離級別:

      ​ DEFAULT:採用 DB預設的事務隔離級別。Mysql的預設為REPEATABLE_READ;Oracle預設為 READ_COMITTED.READ

      ​ UNCOMMITTED:讀未提交。未解決任何併發問題。
      ​ READ_COMMITTED:讀已提交。解決髒讀,存在不可重複讀與幻讀。

      ​ REPEATABLE_READ:可重複讀。解決髒讀、不可重複讀,存在幻讀SERIALIZABLE:序列化。不存在併發問題。

      ​ 2)事務的超時時間:表示一個方法的最長執行時間,如果方法執行超過了時間,事務就回滾

      ​ 3)事務的傳播行為:控制業務方法是不是有事務的,是什麼樣的事務

      ​ 7個傳播行為,表示業務方法呼叫時,事務在方法之間是如何使用的

      <!--!!!
      PROPAGATION REQUIRED
      PROPAGATION_REQUIRES_NEW
      PROPAGATIONsUPPORTS       
      -->
      PROPAGATIONMANDATORY
      PROPAGATION_NESTED
      PROPAGATION_NEVER
      PROPAGATIONNOT_SUPPORTED
      
    3. 事務提交事務,回滾事務的時機
      1)當你的業務方法,執行成功,沒有異常丟擲,當方法執行完畢,spring在方法執行後提交事務。事務管理器commit

      2)當你的業務方法丟擲執行時異常或ERROR,spring執行回滾,呼叫事務管理器的rollback
      執行時異常的定義: RuntimeException 和他的子類都是執行時異常,例如Ntul1PointException , MunberFormatzxcept.
      3)當你的業務方法丟擲非執行時異常,主要是受查異常時,提交事務
      受查異常:在你寫程式碼中,必須處理的異常。例如IOException,SQLException

總結Spring事務:

  1. 管理事務的是 事務管理 和他的實現類
  2. spring的事務是一個統一模型
    1. 指定使用的事務管理器的實現類,使用
    2. 指定哪些類,哪些方法需要加入事務的功能
    3. 指定方法需要的隔離級別,傳播行為,超時

4.2 Spring的事務傳播機制

**Required **解義:如果上下文中已經存在事務,就加入到事務當中

上下文有事務 上下文沒有事務
Required 加入到事務當中 新建事務
Supports 加入到事務當中 非事務方式執行
Mandatory 必須要有事務 丟擲異常
Requires_New 新建事務 新建事務
Not_Supported 事務掛起,方法結束後恢復事務
Never 丟擲runtime異常,強制停止執行
Nested 巢狀事務執行 新建事務

二、SpringMVC

1.1 MVC在B/S下的應用

mvc是一個設計模式

1.2 springmvc框架

過程

1、發起請求到前端控制器

2、前端控制器請求HandlerMapping查詢Handler

​ 根據xml配置、註解進行查詢

3、處理器對映器HandlerMapping向前端控制器返回Handler

4、前端控制器用處理器介面卡去執行Handler

5、理器介面卡執行Handler

6、Handler執行完成給介面卡返回ModelAndView

7、處理器向前端控制器返回ModelAndView

​ ModelAndView是springmvc框架的一個底層物件,包括model 和 view

8、前端控制器請求檢視解析器去進行檢視解析

​ 根據邏輯檢視名解析程真正的檢視jsp

9、檢視解析器向前端控制器返回View

10、前端控制器進行檢視渲染

​ 檢視渲染將模型資料(在ModelAndView中)填充到request域

11、前端控制器向使用者返回響應結果

元件:

1、前端控制器DispatcherServlet,(不需要程式設計師開發)

​ 接收請求,響應結果,相當於轉發器,中央處理器

​ 減少其他元件之間的耦合度

2、處理器對映器HandlerMapping,(不需要程式設計師開發)

​ 根據請求的url查詢Handler

3、處理器介面卡HandlerAdapter(不需要程式設計師開發)

​ 按照特定規則(HandlerAdapter要求的規則)去執行Handler

​ 編寫Handler時按照HandlerAdapter的要求去做才能正確執行Handler

4、處理器Handler,(需要程式設計師開發)

5、檢視解析器View Resolver

​ 檢視解析,根據邏輯檢視域名解析成真正的檢視View

6、檢視View,(需要程式設計師開發jsp)

​ 是一個介面,實現類支援不同的View型別(jsp、freemarker、pdf...)

2、 json資料互動

2.1、使用json互動的原因:

​ json資料格式在介面呼叫中、html頁面中常用,json格式簡單,解析比較方便

2.2、springmvc進行json互動

springmvc中使用jackson的jar包進行json轉換

客戶端請求key / value串
請求的是json串
contenttype=application/json
請求的是key / value
contenttype=
@RequestBody將json串轉成java物件 不需要@RequestBody將json串轉成java物件
@ResponseBody將java物件轉成json輸出 @ResponseBody將java物件轉成json輸出
最後都輸出json資料,為了在前端頁面方便對請求結果進行解析

1、請求json、輸出json,要求請求的是json串,所以在前端頁面中需要將請求的內容轉成json,不太方便

2、請求key / value ,輸出json,比較常用

3、Restful支援

restful是一種開發理念,是對http的一個詮釋,即表現層狀態的轉化

對url進行規範,寫restful格式的url,就是簡潔

非rest的url:http://.../finditems.action?id=001

rest的url風格:http://.../items/001

相關文章