spring
- 1、spring概述
-
- 1.1spring是什麼
- 1.2spring優點
- 1.3spring體系結構
- 2、 IoC 控制反轉
-
- 2.1概念
- 2.2基于注解的DI
-
- 定義 Bean 的注解
- 屬性注入
- 3、AOP 面向切面程式設計
-
- 3.1概念
- 3.2AOP程式設計術語
- 3.3AspectJ 對 AOP 的實作
-
- AspectJ 中常用的通知有五種類型:
- AspectJ 的切入點表達式
- AspectJ 的依賴
- AspectJ 基于注解的 AOP 實作
1、spring概述
1.1spring是什麼
Spring 是于 2003 年興起的一個輕量級的 Java 開發架構,它是為了解決企業應用開發的複雜性而建立的。Spring 的核心是控制反轉(IoC)和面向切面程式設計(AOP)。Spring 是可以在 Java SE/EE 中使用的輕量級開源架構。
Spring 的主要作用就是為代碼“解耦”,降低代碼間的耦合度。就是讓對象和對象(模
塊和子產品)之間關系不是使用代碼關聯,而是通過配置來說明。即在 Spring 中說明對象(子產品)的關系。Spring 根據代碼的功能特點,使用 Ioc 降低業務對象之間耦合度。IoC 使得主業務在互相調用過程中,不用再自己維護關系了,即不用再自己建立要使用的對象了。而是由 Spring容器統一管理,自動“注入”,注入即指派。 而 AOP 使得系統級服務得到了最大複用,且不用再由程式員手工将系統級服務“混雜”到主業務邏輯中了,而是由 Spring 容器統一完成“織入”。
官網:https://spring.io/
1.2spring優點
Spring 是一個架構,是一個半成品的軟體。有 20 個子產品組成。它是一個容器管理對象,容器是裝東西的,Spring 容器不裝文本,數字。裝的是對象。Spring 是存儲對象的容器。
(1) 輕量
Spring 架構使用的 jar 都比較小,一般在 1M 以下或者幾百 kb。Spring 核心功能的所需的 jar 總共在 3M 左右。Spring 架構運作占用的資源少,運作效率高。不依賴其他 jar
(2) 針對接口程式設計,解耦合
Spring 提供了 Ioc 控制反轉,由容器管理對象,對象的依賴關系。原來在程式代碼中的對象建立方式,現在由容器完成。對象之間的依賴解耦合。
Spring 是于 2003 年興起的一個輕量級的 Java 開發架構,它是為了解決企業應用開發的複雜性而建立的。Spring 的核心是控制反轉(IoC)和面向切面程式設計(AOP)。Spring 是可以在 Java SE/EE 中使用的輕量級開源架構。
(3) AOP 程式設計的支援
通過 Spring 提供的 AOP 功能,友善進行面向切面的程式設計,許多不容易用傳統 OOP 實作的功能可以通過 AOP 輕松應付在 Spring 中,開發人員可以從繁雜的事務管理代碼中解脫出來,通過聲明式方式靈活地進行事務的管理,提高開發效率和品質。
(4) 友善內建各種優秀架構
Spring 不排斥各種優秀的開源架構,相反 Spring 可以降低各種架構的使用難度,Spring提供了對各種優秀架構(如 Struts,Hibernate、MyBatis)等的直接支援。簡化架構的使用。Spring 像插線闆一樣,其他架構是插頭,可以容易的組合到一起。需要使用哪個架構,就把這個插頭放入插線闆。不需要可以輕易的移除。
1.3spring體系結構
2、 IoC 控制反轉
2.1概念
控制反轉(IoC,Inversion of Control),是一個概念,是一種思想。指将傳統上由程式代碼直接操控的對象調用權交給容器,通過容器來實作對象的裝配和管理。控制反轉就是對對象控制權的轉移,從程式代碼本身反轉到了外部容器。通過容器實作對象的建立,屬性指派,依賴的管理。
IoC 是一個概念,是一種思想,其實作方式多種多樣。目前比較流行的實作方式是依賴注入。應用廣泛。
依賴:classA 類中含有 classB 的執行個體,在 classA 中調用 classB 的方法完成功能,即 classA對 classB 有依賴。
Ioc 的實作:
依賴注入:DI(Dependency Injection),程式代碼不做定位查詢,這些工作由容器自行完成。依賴注入 DI 是指程式運作過程中,若需要調用另一個對象協助時,無須在代碼中建立被調用者,而是依賴于外部容器,由外部容器建立後傳遞給程式。
Spring 的依賴注入對調用者與被調用者幾乎沒有任何要求,完全支援對象之間依賴關系的管理。Spring 架構使用依賴注入(DI)實作 IoC。
Spring 容器是一個超級大工廠,負責建立、管理所有的 Java 對象,這些 Java 對象被稱為 Bean。Spring 容器管理着容器中 Bean 之間的依賴關系,Spring 使用“依賴注入”的方式來管理 Bean 之間的依賴關系。使用 IoC 實作對象之間的解耦和。
2.2基于注解的DI
定義 Bean 的注解
@Component用于普通java類進行注解
@Repository 用于對 DAO 實作類進行注解
@Service 用于對 Service 實作類進行注解
@Controller 用于對 Controller 實作類進行注解
屬性注入
簡單類型屬性注入@Value
byType 自動注入@Autowired
byName 自動注入@Autowired 與@Qualifier
例如:
@Autowired
@Qualifier("mySchool")
private School school;
JDK 注解@Resource 自動注入
3、AOP 面向切面程式設計
3.1概念
AOP(Aspect Orient Programming),面向切面程式設計。面向切面程式設計是從動态角度考慮程式運作過程。AOP 底層,就是采用動态代理模式實作的。采用了兩種代理:JDK 的動态代理,與 CGLIB的動态代理。
AOP 為 Aspect Oriented Programming 的縮寫,意為:面向切面程式設計,可通過運作期動态代理實作程式功能的統一維護的一種技術。AOP 是 Spring 架構中的一個重要内容。利用 AOP可以對業務邏輯的各個部分進行隔離,進而使得業務邏輯各部分之間的耦合度降低,提高程式的可重用性,同時提高了開發的效率。
面向切面程式設計,就是将交叉業務邏輯封裝成切面,利用 AOP 容器的功能将切面織入到主業務邏輯中。所謂交叉業務邏輯是指,通用的、與主業務邏輯無關的代碼,如安全檢查、事務、日志、緩存等。若不使用 AOP,則會出現代碼糾纏,即交叉業務邏輯與主業務邏輯混合在一起。這樣,會使主業務邏輯變的混雜不清。
例如,轉賬,在真正轉賬業務邏輯前後,需要權限控制、日志記錄、加載事務、結束事務等交叉業務邏輯,而這些業務邏輯與主業務邏輯間并無直接關系。但,它們的代碼量所占比重能達到總代碼量的一半甚至還多。它們的存在,不僅産生了大量的“備援”代碼,還大大幹擾了主業務邏輯—轉賬。
3.2AOP程式設計術語
(1) 切面(Aspect)
切面泛指交叉業務邏輯。上例中的事務處理、日志處理就可以了解為切面。常用的切面是通知(Advice)。實際就是對主業務邏輯的一種增強。
(2) 連接配接點(JoinPoint)
連接配接點指可以被切面織入的具體方法。通常業務接口中的方法均為連接配接點。
(3) 切入點(Pointcut)
切入點指聲明的一個或多個連接配接點的集合。通過切入點指定一組方法。被标記為 final 的方法是不能作為連接配接點與切入點的。因為最終的是不能被修改的,不能被增強的。
(4) 目标對象(Target)
目 标 對 象 指 将 要 被 增 強 的 對 象 。 即 包 含 主 業 務 邏 輯 的 類 的 對 象 。 上 例 中 的StudentServiceImpl 的對象若被增強,則該類稱為目标類,該類對象稱為目标對象。當然,不被增強,也就無所謂目标不目标了。
(5) 通知(Advice)
通知表示切面的執行時間,Advice 也叫增強。上例中的 MyInvocationHandler 就可以了解為是一種通知。換個角度來說,通知定義了增強代碼切入到目标代碼的時間點,是目标方法執行之前執行,還是之後執行等。通知類型不同,切入時間不同。
切入點定義切入的位置,通知定義切入的時間。
3.3AspectJ 對 AOP 的實作
AspectJ 中常用的通知有五種類型:
(1)前置通知
(2)後置通知
(3)環繞通知
(4)異常通知
(5)最終通知
AspectJ 的切入點表達式
AspectJ 定義了專門的表達式用于指定切入點。表達式的原型是:
execution(modifiers-pattern? ret-type-pattern
declaring-type-pattern?name-pattern(param-pattern)
throws-pattern?)
modifiers-pattern] 通路權限類型
ret-type-pattern 傳回值類型
declaring-type-pattern 包名類名
name-pattern(param-pattern) 方法名(參數類型和參數個數)
throws-pattern 抛出異常類型
?表示可選的部分
AspectJ 是一個優秀面向切面的架構,它擴充了 Java 語言,提供了強大的切面實作。以上表達式共 4 個部分。
execution(通路權限 方法傳回值 方法聲明(參數) 異常類型)
切入點表達式要比對的對象就是目标方法的方法名。是以,execution 表達式中明顯就是方法的簽名。注意,表達式中黑色文字表示可省略部分,各部分間用空格分開。在其中可以使用以下符号:
AspectJ 的依賴
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
AspectJ 基于注解的 AOP 實作
定義業務接口與實作類
public interface SomeService {
void doSome();
String doOther();
String surround();
}
@Component
public class SomeServiceImp implements SomeService {
@Override
public void doSome() {
System.out.println("doSome");
}
@Override
public String doOther() {
System.out.println("doOther");
return "hello";
}
@Override
public String surround(){
System.out.println("surround");
return "cao";
}
}
定義切面類
前置通知
@Aspect
@Component
public class MyAspect {
/**
前置通知
*/
@Before("execution(public void com.guet.mybatis.service.imp.SomeServiceImp.doSome())")
public void myBefore(JoinPoint jp){
System.out.println(jp.getSignature());
System.out.println("前置通知");
}
}
後置通知
@Aspect
@Component
public class MyAspect2 {
@AfterReturning( value = "execution(public String com.guet.mybatis.service.imp.SomeServiceImp.doOther())",returning = "result")
public void myAfterReturn(JoinPoint jp,Object result){
System.out.println("後置通知");
System.out.println(jp.getSignature());
System.out.println("傳回值"+(String)result);
}
}
環繞通知
@Aspect
@Component
public class MyAspect3 {
@Around("execution(public String com.guet.mybatis.service.imp.SomeServiceImp.surround())")
public Object mySurround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
Object obj;
System.out.println("前置通知");
obj = proceedingJoinPoint.proceed();
System.out.println("後置通知");
String s = "diaoniam";
return s;
}
}
在目标方法執行之前之後執行。被注解為環繞增強的方法要有傳回值,Object 類型。并且方法可以包含一個 ProceedingJoinPoint 類型的參數。接口 ProceedingJoinPoint 其有一個proceed()方法,用于執行目标方法。若目标方法有傳回值,則該方法的傳回值就是目标方法的傳回值。最後,環繞增強方法将其傳回值傳回。該增強方法實際是攔截了目标方法的執行。