您好,登錄后才能下訂單哦!
小編給大家分享一下java中代理模式的面試題有哪些,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
靜態(tài)代理角色分析:
抽象角色 :一般使用接口或者抽象類來(lái)實(shí)現(xiàn)。
真實(shí)角色 :被代理的角色。
代理角色: 代理真實(shí)角色 , 代理真實(shí)角色后 ,一般會(huì)做一些附屬的操作。
調(diào)用方:使用代理角色來(lái)進(jìn)行一些操作。
我們以租客租客租房子為例,涉及到的對(duì)象有:租客、中介、房東。(房東即為被代理對(duì)象,中介即為代理對(duì)象)
租客通過中介之手租住房東的房子,代理對(duì)象中介需要尋找租客租房,并從中獲取中介費(fèi)用。
代碼實(shí)現(xiàn):
Rent.java
即抽象角色
// 抽象角色:租房 public interface Rent { public void rent(); }
Host.java
即真實(shí)角色
// 真實(shí)角色: 房東,房東要出租房子 public class Host implements Rent{ public void rent() { System.out.println("房屋出租"); } }
Proxy.java
即代理角色
//代理角色:中介 public class Proxy implements Rent { private Host host; public Proxy() { } public Proxy(Host host) { this.host = host; } // 租房 public void rent(){ seeHouse(); host.rent(); fare(); } // 看房 public void seeHouse(){ System.out.println("帶房客看房"); } // 收中介費(fèi) public void fare(){ System.out.println("收中介費(fèi)"); } }
Client.java
調(diào)用方,即客戶
// 客戶類,一般客戶都會(huì)去找代理! public class Client { public static void main(String[] args) { // 房東要租房 Host host = new Host(); // 中介幫助房東 Proxy proxy = new Proxy(host); // 你去找中介! proxy.rent(); } }
靜態(tài)代理的缺點(diǎn):
需要手動(dòng)創(chuàng)建代理類,如果需要代理的對(duì)象多了,那么代理類也越來(lái)越多。
為了解決,這個(gè)問題,就有了動(dòng)態(tài)代理 !
說到動(dòng)態(tài)代理,面試的時(shí)候肯定會(huì)問動(dòng)態(tài)代理的兩種實(shí)現(xiàn)方式:
先來(lái)看公共的 UserService
接口,和 UserServiceImpl
實(shí)現(xiàn)類:
/** * @author csp * @date 2021-06-03 */ public interface UserService { /** * 登錄 */ void login(); /** * 登出 */ void logout(); }
/** * @author csp * @date 2021-06-03 */ public class UserServiceImpl implements UserService{ @Override public void login() { System.out.println("用戶登錄..."); } @Override public void logout() { System.out.println("用戶推出登錄..."); } }
代碼如下:
/** * @author csp * @date 2021-06-03 */ public class JDKProxyFactory implements InvocationHandler { // 目標(biāo)對(duì)象(被代理對(duì)象) private Object target; public JDKProxyFactory(Object target) { super(); this.target = target; } /** * 創(chuàng)建代理對(duì)象 * * @return */ public Object createProxy() { // 1.得到目標(biāo)對(duì)象的類加載器 ClassLoader classLoader = target.getClass().getClassLoader(); // 2.得到目標(biāo)對(duì)象的實(shí)現(xiàn)接口 Class<?>[] interfaces = target.getClass().getInterfaces(); // 3.第三個(gè)參數(shù)需要一個(gè)實(shí)現(xiàn)invocationHandler接口的對(duì)象 Object newProxyInstance = Proxy.newProxyInstance(classLoader, interfaces, this); return newProxyInstance; } /** * 真正執(zhí)行代理增強(qiáng)的方法 * * @param proxy 代理對(duì)象.一般不使用 * @param method 需要增強(qiáng)的方法 * @param args 方法中的參數(shù) * @return */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("JDK 動(dòng)態(tài)代理:登錄/登出前邏輯校驗(yàn)......"); Object invoke = method.invoke(target, args); System.out.println("JDK 動(dòng)態(tài)代理:登錄/登出后日志打印......"); return invoke; } public static void main(String[] args) { // 1.創(chuàng)建對(duì)象 UserServiceImpl userService = new UserServiceImpl(); // 2.創(chuàng)建代理對(duì)象 JDKProxyFactory jdkProxyFactory = new JDKProxyFactory(userService); // 3.調(diào)用代理對(duì)象的增強(qiáng)方法,得到增強(qiáng)后的對(duì)象 UserService userServiceProxy = (UserService) jdkProxyFactory.createProxy(); userServiceProxy.login(); System.out.println("=================================="); userServiceProxy.logout(); } }
輸出結(jié)果如下:
JDK 動(dòng)態(tài)代理:登錄/登出前邏輯校驗(yàn)......
用戶登錄...
JDK 動(dòng)態(tài)代理:登錄/登出后日志打印......
==================================
JDK 動(dòng)態(tài)代理:登錄/登出前邏輯校驗(yàn)......
用戶推出登錄...
JDK 動(dòng)態(tài)代理:登錄/登出后日志打印......
代碼如下:
/** * @author csp * @date 2021-06-03 */ public class CglibProxyFactory implements MethodInterceptor { // 目標(biāo)對(duì)象(被代理對(duì)象) private Object target; // 使用構(gòu)造方法傳遞目標(biāo)對(duì)象 public CglibProxyFactory(Object target) { super(); this.target = target; } /** * 創(chuàng)建代理對(duì)象 * * @return */ public Object createProxy() { // 1.創(chuàng)建Enhancer Enhancer enhancer = new Enhancer(); // 2.傳遞目標(biāo)對(duì)象的class enhancer.setSuperclass(target.getClass()); // 3.設(shè)置回調(diào)操作 enhancer.setCallback(this); return enhancer.create(); } /** * 真正執(zhí)行代理增強(qiáng)的方法 * @param o 代理對(duì)象 * @param method 要增強(qiáng)的方法 * @param objects 要增強(qiáng)方法的參數(shù) * @param methodProxy 要增強(qiáng)的方法的代理 * @return * @throws Throwable */ @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("cglib 動(dòng)態(tài)代理:登錄/登出前邏輯校驗(yàn)......"); Object invoke = method.invoke(target, objects); System.out.println("cglib 動(dòng)態(tài)代理:登錄/登出后日志打印......"); return invoke; } public static void main(String[] args) { // 1.創(chuàng)建對(duì)象 UserServiceImpl userService = new UserServiceImpl(); // 2.創(chuàng)建代理對(duì)象 CglibProxyFactory cglibProxyFactory = new CglibProxyFactory(userService); // 3.調(diào)用代理對(duì)象的增強(qiáng)方法,得到增強(qiáng)后的對(duì)象 UserService userServiceProxy = (UserService) cglibProxyFactory.createProxy(); userServiceProxy.login(); System.out.println("=================================="); userServiceProxy.logout(); } }
測(cè)試結(jié)果如下:
cglib 動(dòng)態(tài)代理:登錄/登出前邏輯校驗(yàn)......
用戶登錄...
cglib 動(dòng)態(tài)代理:登錄/登出后日志打印......
==================================
cglib 動(dòng)態(tài)代理:登錄/登出前邏輯校驗(yàn)......
用戶推出登錄...
cglib 動(dòng)態(tài)代理:登錄/登出后日志打印......
① JDK 動(dòng)態(tài)代理本質(zhì)上是實(shí)現(xiàn)了被代理對(duì)象的接口,而 CGLib 本質(zhì)上是繼承了被代理對(duì)象,覆蓋其中的方法。
② JDK 動(dòng)態(tài)代理只能對(duì)實(shí)現(xiàn)了接口的類生成代理,CGLib 則沒有這個(gè)限制。但是 CGLib 因?yàn)槭褂美^承實(shí)現(xiàn),所以 CGLib 所以無(wú)法對(duì) final
類、private
方法和 static
方法進(jìn)行代理。
③ JDK 動(dòng)態(tài)代理是 JDK 里自帶的,CGLib 動(dòng)態(tài)代理需要引入第三方的 jar
包。
④ 在調(diào)用代理方法上,JDK動(dòng)態(tài)代理是通過反射機(jī)制調(diào)用,CGLib 是通過 FastClass 機(jī)制直接調(diào)用。(看過一篇文章,介紹說 FastClass 簡(jiǎn)單的理解,就是使用一個(gè) index 下標(biāo)作為入?yún)?,可以直接定位到要調(diào)用的方法直接,并進(jìn)行調(diào)用)
在性能上,JDK1.7 之前,由于使用了 FastClass 機(jī)制,CGLib 在執(zhí)行效率上比 JDK 快,但是隨著 JDK 動(dòng)態(tài)代理的不斷優(yōu)化,從 JDK 1.7 開始,JDK 動(dòng)態(tài)代理已經(jīng)明顯比 CGLib 更快了。
根本原因是通過 JDK 動(dòng)態(tài)代理生成的類已經(jīng)繼承了 Proxy 類,所以無(wú)法再使用繼承的方式去對(duì)類實(shí)現(xiàn)代理。
以上是“java中代理模式的面試題有哪些”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。