日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

【Spring】IoC,DI,两种代理方式,AOP定义和使用

發(fā)布時間:2023/12/20 javascript 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Spring】IoC,DI,两种代理方式,AOP定义和使用 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

  • 前言
  • 一、Spring框架中的核心思想?
    • 1.1依賴注入(DI)
    • 【總結(jié)】IOC DI
  • 二、Spring-面向切面編程(AOP)
    • 2.1代理模式舉例
    • 2.2如何開發(fā)一個代理對象?
    • 2.2.1 靜態(tài)代理對象
    • 2.2.2動態(tài)代理對象
    • 2.3面向切面編程
    • 2.3.1Spring aop 編程的編程步驟
    • 2.3.2aop編程舉例
    • 2.4總結(jié)
  • 三、如何用Spring創(chuàng)建復(fù)雜對象?
    • 3.1Spring工廠獲取對象的原理(回顧)


前言


一、Spring框架中的核心思想?

兩個思想:控制反轉(zhuǎn)(IoC, Inversion of Control) 、 面向切面編程(AOP, )

IoC
定義:控制反轉(zhuǎn):控制權(quán)力的反轉(zhuǎn)。
解釋:將原來手動通過new關(guān)鍵字創(chuàng)建對象的權(quán)力交給了Spring,通過在配置文件中配置bean標簽的形式創(chuàng)建對象,交給Spring 由Spring創(chuàng)建對象的過程。

可是,像Tomcat容器,也能夠做到不需要new關(guān)鍵字,就可以使用Servlet,(其實背后就是控制反轉(zhuǎn))。那么控制反轉(zhuǎn)并不是Spring所特有的特性。
因此,Spring在基于IOC基礎(chǔ)上,提出了“依賴注入”(DI,Dependency Injection)。

我們可以發(fā)現(xiàn)Service層經(jīng)常需要調(diào)用DAO層,即需要DAO組件對象, 這種 “需要” 可以稱為 “依賴”,即 依賴DAO組件。

因為DAO組件對象已經(jīng)在Spring中生成了,那么下次Service層在調(diào)用時,只需要在Spring容器中取就好了。

像此時,deptDAO只是有聲明,如果需要時在12行直接調(diào)用save(),會報空指針異常。
那么 第一步 需要誰。就先聲明誰為成員變量,
第二步:為成員變量賦值,為成員變量賦值的過程 ,就稱為依賴注入。

1.1依賴注入(DI)

定義:為組件中成員變量完成賦值過程 ,這個過程就稱之為 依賴注入。
語法:
1.組件對象中需要哪個組件, 就將誰聲明為成員變量 并提供公開的SET方法。(示例如下:)
(提供get方法,會出現(xiàn)代碼冗余)

只有上面操作還不夠,還要經(jīng)過第二步
2.在Spring的配置文件中對應(yīng)的 組件標簽內(nèi) 完成屬性的賦值操作。
下面就是依賴注入的示例:


以上就是依賴注入的過程。
并且可以總結(jié)得知:通過IOC可以創(chuàng)建組件對象, 通過DI 維護了組件與組件之間的調(diào)用關(guān)系
此時
IOC的全部定義概述為:

即控制反轉(zhuǎn), 將原來手動通過new關(guān)鍵字創(chuàng)建對象的權(quán)力交給Spring,由Spring工廠創(chuàng)建對象的過程。
當然,Spring不僅創(chuàng)建對象還要再創(chuàng)建對象的同時,通過DI的方式維護組件與組件的調(diào)用關(guān)系。

DI(set方式注入)基本語法:
DAO層:

Service層:

配置文件的賦值:


啟動工廠測試:

其實在Spring中注入方式主要有三種:
(重點)a.SET注入 : 使用成員變量SET方法形式進行賦值
(了解)b.構(gòu)造注入 : 使用構(gòu)造方法形式 進行屬性的賦值
(了解)c.自動注入 : 通過在配置文件中 完成類中屬性自動賦值

Spring中SET方法的注入語法:
上面已經(jīng)講過的,注入時,把組件對象聲明,然后生成SET方法,
但如果需要注入的不是對象, 而是一個String屬性值、Date類型的還和上面的語法一樣嗎?
可以通過在xml文件中選用value對 八種基本數(shù)據(jù)類型 + String類型 + Date 類型 統(tǒng)一使用 value屬性進行注入



Spring中對日期類型的值注入,只能使用格式為value=“yyyy/MM/dd HH:mm:ss”

總結(jié):


對于Map類型,其鍵值對,根據(jù)具體情況具體寫,總體原則是,對象類型就要用ref, String等類型用value。例如:key-ref,value-ref等

對于properties配置文件,里面也是key-value:,里面都是放String,所以沒有什么key-ref:

【總結(jié)】IOC DI




二、Spring-面向切面編程(AOP)

面向切面的編程,:(AOP,Aspect Oriented Programing )
底層原理:java 代理設(shè)計模式 動態(tài)代理
好處:在保證 原始業(yè)務(wù)功能不變的情況下, 通過代理對象完成 業(yè)務(wù)中附加操作,將業(yè)務(wù)中核心操作 放在目標對象中執(zhí)行,實現(xiàn)了附加操作和核心操作的解耦
在說AOP之前,需要先明白代理設(shè)計模式
java: (Proxy)代理設(shè)計模式

2.1代理模式舉例

小張和小麗網(wǎng)戀,小張(業(yè)務(wù)邏輯調(diào)用者,Main())給小麗的賬號名(如花)(接口Interface)發(fā)消息,本來小麗要給閨蜜做飯,所以就讓小麗閨蜜(代理對象Proxy)幫自己打字,并轉(zhuǎn)述聊天內(nèi)容。在這個過程中小張是不知道手機對面是誰在和自己聊天(接口屏蔽了底層的具體實現(xiàn)邏輯)。
小麗閨蜜的存在,減輕了小麗的負擔,保證了原始業(yè)務(wù)邏輯不變,同時還能使小麗完成一些附加事情。

2.2如何開發(fā)一個代理對象?

2.2.1 靜態(tài)代理對象

a) 代理對象和 業(yè)務(wù)邏輯對象 (真正的業(yè)務(wù)邏輯對象) 實現(xiàn)相同的接口
b) 代理對象中 依賴 真正業(yè)務(wù)邏輯對象
先看看原始業(yè)務(wù)邏輯對象的代碼:存在大量冗余(忙)

以上代碼可以看到,每個方法都出現(xiàn)了大量的代碼冗余,(開啟事務(wù),提交事務(wù)…)
有代理的存在和無代理的存在,能完成的原始功能是一致的,但是有代理的話,可以讓原始業(yè)務(wù)邏輯對象更加專注去處理原來的核心業(yè)務(wù)(處理DAO)。
(靜態(tài))代理對象的代碼:

spring.xml中:

因此有了代理存在,就 不能再調(diào)用原始的業(yè)務(wù)邏輯對象,而是 應(yīng)該調(diào)用代理對象,才能保證原始大的功能不變。


上面講的,為每一個業(yè)務(wù)層 通過手動開發(fā)一個代理對象的過程 稱之為 “靜態(tài)代理對象”

存在問題很明顯,靜態(tài)代理開發(fā),比原先更加復(fù)雜了,(需要多寫一個類),如果為每一個業(yè)務(wù)層開發(fā)一個靜態(tài)代理類,不僅沒有減輕工作量,
甚至讓工作量多了一倍。

解決方案為業(yè)務(wù)層在運行過程中動態(tài)創(chuàng)建代理類,通過動態(tài)代理類去解決現(xiàn)有業(yè)務(wù)層中業(yè)務(wù)代碼冗余問題。

2.2.2動態(tài)代理對象

代理對象:保證原始功能不變的情況下,完成業(yè)務(wù)邏輯中附加操作
原始業(yè)務(wù)邏輯對象:也叫Target,目標對象| 被代理對象稱之為目標對象, 原始業(yè)務(wù)邏輯對象
什么是動態(tài)代理:
在程序運行過程中,通過代碼底層的方式,為指定的類創(chuàng)建動態(tài)代理對象,(不是手工開發(fā)的,是根據(jù)接口創(chuàng)建的)

proxy 用來生成動態(tài)對象的類
參數(shù)1:classLoader 類加載器
參數(shù)2:Class[] 目標對象的接口的類型的數(shù)組 (一個類可以實現(xiàn)多個接口,所以是數(shù)組)
參數(shù)3: InvocationHandler 接口類型 invoke 方法用來書寫額外功能(附加操作)

UserService userService = new UserServiceImpl(); //目標類 //類加載器, ClassLoader classLoader = Thread.currentThread().getContextClassLoader() //Class[] 目標對象的接口 的類型 的數(shù)組 Class[] classes = {UserService.class}; //返回值:創(chuàng)建好的動態(tài)代理對象: //(為目標類創(chuàng)建代理對象,方式是,通過底層的classLoader類加載器, //讀到UserServiceImpl的類信息,把信息加載到內(nèi)存中,然后才能對應(yīng)生成動態(tài)代理) Uservice userServiceDynamicProxy = (UserService)Proxy.newProxyInstancce(classLoader, classes,new InvocationHandler(){ //通過動態(tài)代理對象調(diào)用自己里面代理方法時 會優(yōu)先指定InvocationHandler類中invoke方法@Override //參數(shù)1:當前創(chuàng)建好的代理對象; 參數(shù)2:當前代理對象執(zhí)行的方法對象, 參數(shù)3:當前代理對象執(zhí)行方法的參數(shù)public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{System.outprintln("當前執(zhí)行的方法:"+method.getName());System.outprintln("當前執(zhí)行的方法的參數(shù):"+args[0]);try{System.outprintln("開啟事務(wù)");//調(diào)用目標類中業(yè)務(wù)方法,通過反射機制,調(diào)用目標類中當前方法Object invoke = method.invoke(new UserServiceImpl(), args)System.outprintln("提交事務(wù)");return invoke;}catch(Exception e){e.printStackTrace();System.out.println("回滾事務(wù)");}return null;}}); String name =proxy.findAll("小明"); //通過動態(tài)代理對象調(diào)用代理中的方法,執(zhí)行這里時,會跳到上面執(zhí)行@Override的方法

第一個參數(shù)是類加載器,為什么呢?
讀接口的信息,底層操作字節(jié)碼,讀字節(jié)碼 動態(tài)生成對象,classLoader就是用來讀class文件,讀類信息的
classes,告訴基于哪個目標類的接口,去生成代理對象

2.3面向切面編程

下圖方框中標記的代碼,我們稱為附加操作,附加操作在AOP中被稱為通知(Advice)
通知(Advice):除了目標方法以外的操作都稱之為通知 附加功能 事務(wù)通知 日志通知 性能通知…
切入點(Pointcut): 指定開發(fā)好的 通知 應(yīng)用于項目中 哪些組件中 哪些方法,通常通知多用于業(yè)務(wù)層
切面(Aspect):通知(Advice) + 切入點 (pointcut)

環(huán)繞通知:圍繞目標方法執(zhí)行的通知

AOP 面向切面編程:
1.開發(fā)通知類(附加功能)
2.配置切面點
3.組裝切面(Aspect)

2.3.1Spring aop 編程的編程步驟

1.引入aop編程相關(guān)依賴

spring-aop、 spring-expression 、spring-aspect

2.項目開發(fā)額外功能通知

環(huán)繞通知 MethodIntercept
前置通知 MethodforAdvice
后置通知 AfterReturningAdvice
異常通知 ThrowsAdvice

3.配置切面 (在spring.xml中完成)
a).注冊通知類

<bean id ="" class="xxxAdvice">

b).組裝切面 aspect = advice + pointcut

<aop:config><aop:pointcut id="" expression="execution()"/><aop:advisor advice-ref="" pointcut-ref=""/> </aop:config>

2.3.2aop編程舉例


上面程序中第8、14行,只是方法名稱不同,存在冗余,因此可通過切面編程優(yōu)化。
解決: 自己寫一個前置通知,這個要實現(xiàn)框架中提供的接口 (implements MethodBeforeAdvice)


上述代碼中,expression="execution(* aop.EmpServiceImpl.*(..))"
第一個*代表 可 任意類型的返回值
第二個 參數(shù) aop.EmpServiceImpl.*(..)這個包名 表示 切入點在 aop.EmpServiceImpl類下的所有方法。如果寫成aop.*ServiceImpl.*.(..)則表示,切入點在aop包下的所有以ServiceImpl結(jié)尾的類,都會切入切面。

上述在spring.xml中配置的代碼,只要發(fā)現(xiàn)了有<aop.advisor>,那么就會根據(jù)該句中的pointcut-ref=""/>生成動態(tài)代理對象,

2.4總結(jié)



說明:
在implements MethodBeforeAdvice之后,重寫的這個before()已經(jīng)把InvokHandler中的invoke方法做了提取,提取成了 各種各樣的通知,

這才使得,當只要切入成功,這里通過getBean得到的empService對象變成了代理對象, 它會優(yōu)先執(zhí)行代理對象的方法。然后再調(diào)用dao執(zhí)行業(yè)務(wù)邏輯方法

三、如何用Spring創(chuàng)建復(fù)雜對象?

3.1Spring工廠獲取對象的原理(回顧)


為什么經(jīng)過上面的a)b)c)三步,工廠可以獲取到組件對象?
因為是反射機制
通過Class.forName("全限定名"),讀取類的信息,然后又調(diào)用 newInstance()調(diào)用類的構(gòu)造方法進行對象的創(chuàng)建

3.通過工廠創(chuàng)建簡單對象
簡單對象:可以直接通過new關(guān)鍵字 創(chuàng)建的對象 ,統(tǒng)一稱為 簡單對象
工廠創(chuàng)建簡單對象時直接通過<bean id="xxx" class="xxx">完成

4.通過工廠創(chuàng)建復(fù)雜對象
復(fù)雜對象: 不能直接通過new關(guān)鍵字進行創(chuàng)建對象,例如:接口類型 | Collection | 抽象類類型 Calender(日歷)/ MessageDigest(加密)…

對象名FactoryBean implements FactoryBean<Calender|Connection|復(fù)雜對象>{ } 例如:創(chuàng)建Calender復(fù)雜對象,1) implements+ 2) @override public class CalenderFactoryBean implements FactoryBean<Calender> {//用來書寫復(fù)雜對象的創(chuàng)建方式@Overridepublic Calender getObject() throws Exception{return Calender.getInstance();}//指定創(chuàng)建的復(fù)雜對象的類型@Overridepublic Class<?> getObjectType(){return Calender.class;}//用來指定創(chuàng)建的對象模式,單例或多例@Overridepublic boolean isSingleton(){return false;} }

工廠創(chuàng)建日歷(復(fù)雜)對象:

工廠創(chuàng)建連接對象:

在工廠中獲取復(fù)雜對象的方式也是用<bean>

代碼如下(示例):

總結(jié)

以上是生活随笔為你收集整理的【Spring】IoC,DI,两种代理方式,AOP定义和使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。