javascript
【Spring】IoC,DI,两种代理方式,AOP定义和使用
文章目錄
- 前言
- 一、Spring框架中的核心思想?
- 1.1依賴注入(DI)
- 【總結】IOC DI
- 二、Spring-面向切面編程(AOP)
- 2.1代理模式舉例
- 2.2如何開發一個代理對象?
- 2.2.1 靜態代理對象
- 2.2.2動態代理對象
- 2.3面向切面編程
- 2.3.1Spring aop 編程的編程步驟
- 2.3.2aop編程舉例
- 2.4總結
- 三、如何用Spring創建復雜對象?
- 3.1Spring工廠獲取對象的原理(回顧)
前言
一、Spring框架中的核心思想?
兩個思想:控制反轉(IoC, Inversion of Control) 、 面向切面編程(AOP, )
IoC
定義:控制反轉:控制權力的反轉。
解釋:將原來手動通過new關鍵字創建對象的權力交給了Spring,通過在配置文件中配置bean標簽的形式創建對象,交給Spring 由Spring創建對象的過程。
可是,像Tomcat容器,也能夠做到不需要new關鍵字,就可以使用Servlet,(其實背后就是控制反轉)。那么控制反轉并不是Spring所特有的特性。
因此,Spring在基于IOC基礎上,提出了“依賴注入”(DI,Dependency Injection)。
我們可以發現Service層經常需要調用DAO層,即需要DAO組件對象, 這種 “需要” 可以稱為 “依賴”,即 依賴DAO組件。
因為DAO組件對象已經在Spring中生成了,那么下次Service層在調用時,只需要在Spring容器中取就好了。
像此時,deptDAO只是有聲明,如果需要時在12行直接調用save(),會報空指針異常。
那么 第一步 需要誰。就先聲明誰為成員變量,
第二步:為成員變量賦值,為成員變量賦值的過程 ,就稱為依賴注入。
1.1依賴注入(DI)
定義:為組件中成員變量完成賦值過程 ,這個過程就稱之為 依賴注入。
語法:
1.組件對象中需要哪個組件, 就將誰聲明為成員變量 并提供公開的SET方法。(示例如下:)
(提供get方法,會出現代碼冗余)
只有上面操作還不夠,還要經過第二步
2.在Spring的配置文件中對應的 組件標簽內 完成屬性的賦值操作。
下面就是依賴注入的示例:
以上就是依賴注入的過程。
并且可以總結得知:通過IOC可以創建組件對象, 通過DI 維護了組件與組件之間的調用關系
此時
IOC的全部定義概述為:
即控制反轉, 將原來手動通過new關鍵字創建對象的權力交給Spring,由Spring工廠創建對象的過程。
當然,Spring不僅創建對象還要再創建對象的同時,通過DI的方式維護組件與組件的調用關系。
DI(set方式注入)基本語法:
DAO層:
Service層:
配置文件的賦值:
啟動工廠測試:
其實在Spring中注入方式主要有三種:
(重點)a.SET注入 : 使用成員變量SET方法形式進行賦值
(了解)b.構造注入 : 使用構造方法形式 進行屬性的賦值
(了解)c.自動注入 : 通過在配置文件中 完成類中屬性自動賦值
Spring中SET方法的注入語法:
上面已經講過的,注入時,把組件對象聲明,然后生成SET方法,
但如果需要注入的不是對象, 而是一個String屬性值、Date類型的還和上面的語法一樣嗎?
可以通過在xml文件中選用value對 八種基本數據類型 + String類型 + Date 類型 統一使用 value屬性進行注入
Spring中對日期類型的值注入,只能使用格式為value=“yyyy/MM/dd HH:mm:ss”
總結:
對于Map類型,其鍵值對,根據具體情況具體寫,總體原則是,對象類型就要用ref, String等類型用value。例如:key-ref,value-ref等
對于properties配置文件,里面也是key-value:,里面都是放String,所以沒有什么key-ref:
【總結】IOC DI
二、Spring-面向切面編程(AOP)
面向切面的編程,:(AOP,Aspect Oriented Programing )
底層原理:java 代理設計模式 動態代理
好處:在保證 原始業務功能不變的情況下, 通過代理對象完成 業務中附加操作,將業務中核心操作 放在目標對象中執行,實現了附加操作和核心操作的解耦
在說AOP之前,需要先明白代理設計模式
java: (Proxy)代理設計模式
2.1代理模式舉例
小張和小麗網戀,小張(業務邏輯調用者,Main())給小麗的賬號名(如花)(接口Interface)發消息,本來小麗要給閨蜜做飯,所以就讓小麗閨蜜(代理對象Proxy)幫自己打字,并轉述聊天內容。在這個過程中小張是不知道手機對面是誰在和自己聊天(接口屏蔽了底層的具體實現邏輯)。
小麗閨蜜的存在,減輕了小麗的負擔,保證了原始業務邏輯不變,同時還能使小麗完成一些附加事情。
2.2如何開發一個代理對象?
2.2.1 靜態代理對象
a) 代理對象和 業務邏輯對象 (真正的業務邏輯對象) 實現相同的接口
b) 代理對象中 依賴 真正業務邏輯對象
先看看原始業務邏輯對象的代碼:存在大量冗余(忙)
以上代碼可以看到,每個方法都出現了大量的代碼冗余,(開啟事務,提交事務…)
有代理的存在和無代理的存在,能完成的原始功能是一致的,但是有代理的話,可以讓原始業務邏輯對象更加專注去處理原來的核心業務(處理DAO)。
(靜態)代理對象的代碼:
spring.xml中:
因此有了代理存在,就 不能再調用原始的業務邏輯對象,而是 應該調用代理對象,才能保證原始大的功能不變。
上面講的,為每一個業務層 通過手動開發一個代理對象的過程 稱之為 “靜態代理對象”
存在問題:很明顯,靜態代理開發,比原先更加復雜了,(需要多寫一個類),如果為每一個業務層開發一個靜態代理類,不僅沒有減輕工作量,
甚至讓工作量多了一倍。
解決方案:為業務層在運行過程中動態創建代理類,通過動態代理類去解決現有業務層中業務代碼冗余問題。
2.2.2動態代理對象
代理對象:保證原始功能不變的情況下,完成業務邏輯中附加操作
原始業務邏輯對象:也叫Target,目標對象| 被代理對象稱之為目標對象, 原始業務邏輯對象
什么是動態代理:
在程序運行過程中,通過代碼底層的方式,為指定的類創建動態代理對象,(不是手工開發的,是根據接口創建的)
proxy 用來生成動態對象的類
參數1:classLoader 類加載器
參數2:Class[] 目標對象的接口的類型的數組 (一個類可以實現多個接口,所以是數組)
參數3: InvocationHandler 接口類型 invoke 方法用來書寫額外功能(附加操作)
第一個參數是類加載器,為什么呢?
讀接口的信息,底層操作字節碼,讀字節碼 動態生成對象,classLoader就是用來讀class文件,讀類信息的
classes,告訴基于哪個目標類的接口,去生成代理對象
2.3面向切面編程
下圖方框中標記的代碼,我們稱為附加操作,附加操作在AOP中被稱為通知(Advice)
通知(Advice):除了目標方法以外的操作都稱之為通知 附加功能 事務通知 日志通知 性能通知…
切入點(Pointcut): 指定開發好的 通知 應用于項目中 哪些組件中 哪些方法,通常通知多用于業務層
切面(Aspect):通知(Advice) + 切入點 (pointcut)
環繞通知:圍繞目標方法執行的通知
AOP 面向切面編程:
1.開發通知類(附加功能)
2.配置切面點
3.組裝切面(Aspect)
2.3.1Spring aop 編程的編程步驟
1.引入aop編程相關依賴
spring-aop、 spring-expression 、spring-aspect
2.項目開發額外功能通知
環繞通知 MethodIntercept
前置通知 MethodforAdvice
后置通知 AfterReturningAdvice
異常通知 ThrowsAdvice
3.配置切面 (在spring.xml中完成)
a).注冊通知類
b).組裝切面 aspect = advice + pointcut
<aop:config><aop:pointcut id="" expression="execution()"/><aop:advisor advice-ref="" pointcut-ref=""/> </aop:config>2.3.2aop編程舉例
上面程序中第8、14行,只是方法名稱不同,存在冗余,因此可通過切面編程優化。
解決: 自己寫一個前置通知,這個要實現框架中提供的接口 (implements MethodBeforeAdvice)
上述代碼中,expression="execution(* aop.EmpServiceImpl.*(..))"
第一個*代表 可 任意類型的返回值
第二個 參數 aop.EmpServiceImpl.*(..)這個包名 表示 切入點在 aop.EmpServiceImpl類下的所有方法。如果寫成aop.*ServiceImpl.*.(..)則表示,切入點在aop包下的所有以ServiceImpl結尾的類,都會切入切面。
上述在spring.xml中配置的代碼,只要發現了有<aop.advisor>,那么就會根據該句中的pointcut-ref=""/>生成動態代理對象,
2.4總結
說明:
在implements MethodBeforeAdvice之后,重寫的這個before()已經把InvokHandler中的invoke方法做了提取,提取成了 各種各樣的通知,
這才使得,當只要切入成功,這里通過getBean得到的empService對象變成了代理對象, 它會優先執行代理對象的方法。然后再調用dao執行業務邏輯方法
三、如何用Spring創建復雜對象?
3.1Spring工廠獲取對象的原理(回顧)
為什么經過上面的a)b)c)三步,工廠可以獲取到組件對象?
因為是反射機制
通過Class.forName("全限定名"),讀取類的信息,然后又調用 newInstance()調用類的構造方法進行對象的創建
3.通過工廠創建簡單對象
簡單對象:可以直接通過new關鍵字 創建的對象 ,統一稱為 簡單對象
工廠創建簡單對象時直接通過<bean id="xxx" class="xxx">完成
4.通過工廠創建復雜對象
復雜對象: 不能直接通過new關鍵字進行創建對象,例如:接口類型 | Collection | 抽象類類型 Calender(日歷)/ MessageDigest(加密)…
工廠創建日歷(復雜)對象:
工廠創建連接對象:
在工廠中獲取復雜對象的方式也是用<bean>
代碼如下(示例):
總結
以上是生活随笔為你收集整理的【Spring】IoC,DI,两种代理方式,AOP定义和使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 租房/搬家必备物品清单
- 下一篇: 【win10】电脑蓝牙开关找不到了的解决