大家好!我是CSRobot,從今天開始,我將會發布一些技術文章,內容就是結合春招以來的面試所遇到的問題進行分享,首先會對知識點進行一個探討和整理,在最后會給出一些面試題并作出解答,希望可以幫助到大家!今天知識點是動態代理,會分從以下幾個方面進行探討:
靜態代理 JDK動態代理 Cglib動態代理 面試題分享 在java中,要說到動態代理,那么首先需要聊聊靜態代理
一、靜態代理 靜態代理是代理類在編譯期間就創建好了,不是編譯器生成的代理類,而是手動創建的類。在編譯時就已經將接口,被代理類,代理類等確定下來。以下以一個例子來說明靜態代理的實現
1、實現步驟 //創建服務接口
public interface BuyHouse {void buyHouse();
}
//實現接口
public class BuyHouseImpl implements BuyHouse {@Overridepublic void buyHouse() {System.out.println("我要買房子!");}
}
創建代理類實現服務接口,在代理類中手動增強: BuyHouseProxy public class BuyHouseProxy implements BuyHouse {private BuyHouse buyHouse;public BuyHouseProxy(final BuyHouse buyHouse) {this.buyHouse = buyHouse;}//手動增強buyHouse方法@Overridepublic void buyHouse() {System.out.println("買房前準備");buyHouse.buyHouse();System.out.println("買房后裝修");}
}
@Test
public void test() {//未增強的類BuyHouse buyHouse = new BuyHouseImpl();buyHouse.buyHouse();//創建代理類BuyHouseProxy buyHouseProxy = new BuyHouseProxy(buyHouse);buyHouseProxy.buyHouse();
}
我要買房子!
買房前準備
我要買房子!
買房后裝修
二、動態代理 ? Java動態代理的優勢是實現無侵入式的代碼擴展,也就是方法的增強;讓你可以在不用修改源碼的情況下,增強一些方法;在方法的前后你可以做你任何想做的事情。
? 在java的動態代理中,主要有兩種實現方式,首先是基于反射的JDK動態代理實現;其次是cglib的字節碼技術的實現
1、JDK動態代理 通過實現 InvocationHandler 接口創建自己的調用處理器 通過為 Proxy 類指定 ClassLoader 對象和一組 interface 來創建動態代理類 通過反射機制獲得動態代理類的構造函數,其唯一參數類型是調用處理器接口類型 通過構造函數創建動態代理類實例,構造時調用處理器對象作為參數被傳入 代理類名稱是包名+$Proxy+id序號 JDK動態代理只能代理接口而不能代理類,原因大家可以根據jdk動態代理的實現步驟大膽推斷一下,后文會給出答案 創建服務接口 //創建服務接口
public interface BuyHouse {void buyHouse();
}public class BuyHouseImpl implements BuyHouse {@Overridepublic void buyHouse() {System.out.println("我要買房子!");}
}
public class DynamicProxyHandler implements InvocationHandler{private Object object;public DynamicProxyHandler(final Object object) {this.object = object;}//invoke方法對業務進行增強@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("買房前準備");Object result = method.invoke(object, args);System.out.println("買房后裝修");return result;}public Object getProxyInstance(){return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);}
}
@Testpublic void test1() {//創建需要被代理的類BuyHouse buyHouse = new BuyHouseImpl();//創建動態代理處理器DynamicProxyHandler DP = new DynamicProxyHandler(buyHouse);//獲得代理類BuyHouse proxyBuyHouse = DP.getProxyInstance();proxyBuyHouse.buyHouse();}
買房前準備
我要買房子!
買房后裝修
2、Cglib動態代理 在cglib中提供了一個Enhance類來創建代理類,類似于jdk動態代理中的Proxy類。
<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>2.2.2</version>
</dependency>
//創建服務接口
public interface BuyHouse {void buyHouse();
}public class BuyHouseImpl implements BuyHouse {@Overridepublic void buyHouse() {System.out.println("我要買房子!");}
}
public class CglibProxy implements MethodInterceptor{private Object target;public Object getInstance(final Object target) {this.target = target;Enhancer enhancer = new Enhancer();enhancer.setSuperclass(this.target.getClass());enhancer.setCallback(this);return enhancer.create();}@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("買房前準備");Object result = proxy.invokeSuper(obj, args);System.out.println("買房后裝修");return result;}
}
@Test
public void test3(){BuyHouse buyHouse = new BuyHouseImpl();CglibProxy cglibProxy = new CglibProxy();BuyHouseImpl buyHouseCglibProxy = (BuyHouseImpl)cglibProxy.getInstance(buyHouse);buyHouseCglibProxy.buyHouse();
}
三、面試題 1、動態代理是什么?
動態代理:為其他對象提供一個代理以控制對某個對象的訪問。代理類主要負責為委托了(真實對象)預處理消息、過濾消息、傳遞消息給委托類,代理類不現實具體服務,而是利用委托類來完成服務,并將執行結果封裝處理
2、為什么不使用靜態代理而使用動態代理?
通過前文大家也可以理解了,靜態代理是代理類在編譯期間就創建好了,不是編譯器生成的代理類,需要手動創建的類。在編譯時就已經將接口,被代理類,代理類等確定下來。如果我們有很多類很多接口需要代理,那么我們就只能使用代碼提前寫死,不夠靈活;使用了動態代理之后,我們不需要手動創建代理類,全部交給代理去完成對代理類的創建,實現無侵入式的代碼擴展,這也是符合面向對象編程原則的操作。
3、JDK動態代理為什么只能代理接口而不能代理類?
通過JDK動態代理實現步驟我們就可以看到,我們通過Proxy類的newProxyInstance方法來生成代理對象,代理類繼承了Proxy類并且實現了要代理的接口,由于java不支持多繼承,所以JDK動態代理不能代理類
4、JDK動態代理和CgLib動態代理的區別?
1)JDK動態代理只能代理接口而不能代理類,CgLib對于接口和類都可以實現代理
2)JDK動態代理底層使用反射的方式實現;而CgLib采用了非常底層的字節碼技術,其原理是通過目標類的字節碼為一個類創建子類,并在子類中采用方法攔截的技術攔截所有父類方法的調用,順勢織入橫切邏輯。代理類將目標類作為自己的父類并為其中的每個非final委托方法創建兩個方法
CSRobot
總結
以上是生活随笔 為你收集整理的利用代码分别实现jdk动态代理和cglib动态代理_面试之动态代理 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。