網(wǎng)絡(luò)商城網(wǎng)站怎樣做關(guān)鍵詞優(yōu)化專業(yè)網(wǎng)店推廣
目錄
Spring AOP原理
代理模式
代理模式中的主要角色
靜態(tài)代理
?動(dòng)態(tài)代理
總結(jié):面試題
什么是AOP?
Spring AOP實(shí)現(xiàn)的方式有哪些?
Spring AOP實(shí)現(xiàn)原理?
Spring使用的是哪種代理方式?
JDK和CGLIB動(dòng)態(tài)代理的區(qū)別?
Spring AOP原理
代理模式
代理模式, 也叫委托模式.
定義: 為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問. 它的作用就是通過提供一個(gè)代理類, 讓我們?cè)谡{(diào)用目標(biāo)方法的時(shí)候, 不再是直接對(duì)目標(biāo)方法進(jìn)行調(diào)用, 而是通過代理類間接調(diào)用.
在某些情況下, 一個(gè)對(duì)象不適合或者不能直接引用另一個(gè)對(duì)象, 而代理對(duì)象可以在客戶端和目標(biāo)對(duì)象之間起到中介的作用.
使用代理前:
?
使用代理后:
比如當(dāng)進(jìn)行房屋租賃時(shí), 房主會(huì)將房屋授權(quán)給中介, 由中介來代理看房, 房屋咨詢等服務(wù).
代理模式中的主要角色
1.Subject: 業(yè)務(wù)接口類. 可以是抽象類或者接口(不一定有)
2.RealSubject: 業(yè)務(wù)實(shí)現(xiàn)類. 具體的業(yè)務(wù)執(zhí)行, 也就是被代理對(duì)象.
3.Proxy:代理類. RealSubject的代理.?
譬如房屋租賃
Subject: 就是提前定義了房東要做的事情, 交給中介代理, 也是中介要做的事情.
RealSubject: 房東
Proxy: 中介
UML類圖如下:
?
代理模式可以在不修改被代理對(duì)象的基礎(chǔ)上, 通過擴(kuò)展代理類, 進(jìn)行一些功能的附加和增強(qiáng).
根據(jù)代理的創(chuàng)建時(shí)期, 代理模式分為靜態(tài)代理和動(dòng)態(tài)代理.?
靜態(tài)代理: 由程序員創(chuàng)建代理類或特定工具自動(dòng)生成源代碼再對(duì)其編譯, 讓程序運(yùn)行前代理類的 .class 文件就已經(jīng)存在了.
動(dòng)態(tài)代理: 在程序運(yùn)行時(shí), 運(yùn)用反射機(jī)制動(dòng)態(tài)創(chuàng)建而成.
靜態(tài)代理
靜態(tài)代理: 在程序運(yùn)行前, 代理類的.class文件就已經(jīng)存在了. (在出租房子之前, 中介已經(jīng)做好了相關(guān)的工作, 就等租戶來租房子了).
以房屋租賃為例編寫代碼:
1.定義接口(定義房東要做的事情, 也是中介需要做的事情).
public interface HouseSubject {void rentHouse();
}
2.實(shí)現(xiàn)接口(房東出租房子)
public class RealHouseSubject implements HouseSubject{@Overridepublic void rentHouse() {System.out.println("我是房東, 我出租房?");}
}
3.代理(中介, 幫房東出租房子)
public class HouseProxy implements HouseSubject{//將被代理對(duì)象聲明為成員變量private HouseSubject houseSubject;public HouseProxy(HouseSubject houseSubject) {this.houseSubject = houseSubject;}@Overridepublic void rentHouse() {//開始代理System.out.println("我是中介, 開始代理");//代理房東出租房?houseSubject.rentHouse();//代理結(jié)束System.out.println("我是中介, 代理結(jié)束");}
}
4.使用:
public class StaticMain {public static void main(String[] args) {HouseSubject subject = new RealHouseSubject();//創(chuàng)建代理類HouseProxy proxy = new HouseProxy(subject);//通過代理類訪問?標(biāo)?法proxy.rentHouse();}
}
運(yùn)行結(jié)果:
?
上面代理的實(shí)現(xiàn)方式就是靜態(tài)代理.
從上述程序中可以看出, 雖然靜態(tài)代理完成了對(duì)目標(biāo)對(duì)象的代理, 但是由于代碼都寫死了, 對(duì)目標(biāo)對(duì)象的每個(gè)方法的增強(qiáng)都是手動(dòng)完成, 非常不靈活.
比如當(dāng)增加業(yè)務(wù)時(shí)(增加房屋出售), 就還是要編寫大量代碼.
我們修改接口(Subject)和業(yè)務(wù)實(shí)現(xiàn)類(RealSubject)時(shí), 還需要修改代理類(Proxy).
同樣地, 如果有新增接口(Subject)和業(yè)務(wù)實(shí)現(xiàn)類(RealSubject), 也需要對(duì)每個(gè)業(yè)務(wù)實(shí)現(xiàn)類新增代理類(Proxy).
?動(dòng)態(tài)代理
相比于靜態(tài)代理來說, 動(dòng)態(tài)代理更加靈活.
我們不需要針對(duì)每個(gè)目標(biāo)對(duì)象都單獨(dú)創(chuàng)建一個(gè)代理對(duì)象, 而是把這個(gè)創(chuàng)建代理對(duì)象的工作推遲到程序運(yùn)行時(shí)由JVM實(shí)現(xiàn). 也就是說動(dòng)態(tài)代理在程序運(yùn)行時(shí), 更具需要?jiǎng)討B(tài)創(chuàng)建生成.
比如房屋中介, 我不需要提前預(yù)測(cè)都有哪些業(yè)務(wù), 而是業(yè)務(wù)來了我再根據(jù)情況創(chuàng)建.
?Java也對(duì)動(dòng)態(tài)代理進(jìn)行了實(shí)現(xiàn), 并給我們提供了一些API, 常見的實(shí)現(xiàn)方式有兩種:
1.JDK動(dòng)態(tài)代理.
2.CGLIB動(dòng)態(tài)代理.
?一般代理模式開發(fā)人員基本用不著,一般是開發(fā)框架的人用的, 所以不過多介紹(看了估計(jì)也容易忘), 僅給出代碼:
//JDK代理
public class JDKInvocationHandler implements InvocationHandler {private RealHouseSubject target;public JDKInvocationHandler(RealHouseSubject target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("開始代理");Object o = method.invoke(target, args);System.out.println("結(jié)束代理");return o;}
}//main方法RealHouseSubject subject = new RealHouseSubject();Subject proxy= (Subject)Proxy.newProxyInstance(subject.getClass().getClassLoader(),new Class[]{Subject.class},new JDKInvocationHandler(subject));proxy.rentHouse();
?主要這里注意兩個(gè)區(qū)別:
JDK可以代理接口, 不可以代理類.
CGLIB既可以代理接口也可以代理類.
?
注意Spring和SpringBoot在這里AOP的實(shí)現(xiàn)也是有差異的, 代理工廠中有一個(gè)參數(shù)proxyTargetClass. 默認(rèn)Spring是false, 默認(rèn)接口使用jdk代理. SpringBoot從2.x之后設(shè)置為true, 默認(rèn)全部使用CGLib實(shí)現(xiàn)代理.?
總結(jié):面試題
什么是AOP?
答: AOP是一種思想, 是對(duì)某一類事情的集中處理. Spring框架實(shí)現(xiàn)了AOP, 所以稱為SpringAOP.
Spring AOP實(shí)現(xiàn)的方式有哪些?
1.基于注解@Aspect來實(shí)現(xiàn).
2.基于自己寫的@MyAspect自定義注解來實(shí)現(xiàn)
3.基于XML配置的方式實(shí)現(xiàn).
4.基于代理實(shí)現(xiàn).?
Spring AOP實(shí)現(xiàn)原理?
Spring AOP主要使用到了動(dòng)態(tài)代理的方式: 動(dòng)態(tài)代理是一種在運(yùn)行時(shí)生成代理對(duì)象的機(jī)制, Spring AOP利用動(dòng)態(tài)代理技術(shù)在方法調(diào)用時(shí)將切面邏輯織入目標(biāo)對(duì)象中, 實(shí)現(xiàn)橫切關(guān)注點(diǎn)的功能. 具體來說, Spring AOP使用JDK動(dòng)態(tài)代理和CGLIB動(dòng)態(tài)代理來實(shí)現(xiàn)對(duì)目標(biāo)對(duì)象的代理, 以便在方法調(diào)用前后執(zhí)行額外邏輯.
Spring使用的是哪種代理方式?
在Spring中, 代理工廠中的proxyTargetClass 默認(rèn)為false. 如果實(shí)現(xiàn)了接口, 就是用JDK代理. 如果未實(shí)現(xiàn)接口只有實(shí)現(xiàn)類, 就是用CGLib代理.
從Spring Boot從2.x之后, proxyTargetClass默認(rèn)為true, 默認(rèn)使用CGLib代理
JDK和CGLIB動(dòng)態(tài)代理的區(qū)別?
JDK動(dòng)態(tài)代理適用于代理實(shí)現(xiàn)了接口的對(duì)象, 而CGLIB動(dòng)態(tài)代理適用于代理沒有實(shí)現(xiàn)接口的對(duì)象. JDK動(dòng)態(tài)代理利用反射生成代理對(duì)象. 而CGLIB動(dòng)態(tài)代理則是通過繼承目標(biāo)對(duì)象并重寫方法來實(shí)現(xiàn)代理.?