Java 深入淺出講解代理模式
1、動態(tài)代理模式
動態(tài)代理的特點:
- 當代理對象的時候,不需要實現(xiàn)接口
- 代理對象的生成,是利用JDK的API,動態(tài)的在內存中構建代理對象(需要我們指定創(chuàng)建代理對象/目標對象實現(xiàn)的接口的類型)
動態(tài)代理的別稱:JDK代理、接口代理
2、JDK動態(tài)代理
類圖:
Java動態(tài)代理類位于java.lang.reflect包下
一般主要涉及到以下兩個類:
1、Interface InvocationHandler : 該接口中僅定義了一個方法public object invoke(Object obj,Method method, Object[] args) 在實際使用時,第一個參數(shù)obj一般是指代理類,method是被代理的方法,args為該方法的參數(shù)數(shù)組。這個抽象方法在代理類中動態(tài)實現(xiàn)。
2、Proxy:該類即為動態(tài)代理類
static Object newProxyInstance(ClassLoader loader, Class[] interfaces,InvocationHandler h):
返回代理類的一個實例,返回后的代理類可以當作被代理類使用(可使用被代理類的在接口中聲明過的方法)
動態(tài)代的實現(xiàn)步驟:
- 創(chuàng)建一個實現(xiàn)接口InvocationHandler的類,它必須實現(xiàn)invoke方法
- 創(chuàng)建被代理的類以及接口
- 調用Proxy的靜態(tài)方法,創(chuàng)建一個代理類:
newProxyInstance(ClassLoader loader,Class[]
- 通過代理調用方法
3、JDK動態(tài)代理代碼演示
比如現(xiàn)在有一個汽車駕駛的方法:
public interface Moveable { void move(); }
現(xiàn)在有一輛汽車:
//實現(xiàn)Moveable 接口,并隨機暫停一段時間 import java.util.Random; public class Car implements Moveable{ @Override public void move() { try{ Thread.sleep(new Random().nextInt(1000)); System.out.println("汽車行駛中"); } catch (InterruptedException e) { e.printStackTrace(); } } }
時間代理類:
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class TimeHandler implements InvocationHandler{ public TimeHandler(Object target){ super(); this.target = target; } private Object target; /** * * @param proxy :被代理的對象 * @param method:被代理對象的方法 * @param args:方法的參數(shù) * @return * @throws Throwable * 返回值:Object 方法的返回值 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { long startTime = System.currentTimeMillis(); System.out.println("汽車開始行使"); method.invoke(target); long endTime = System.currentTimeMillis(); System.out.println("汽車行駛結束,行駛的時間為:"+(endTime-startTime)+"毫秒"); return null; } }
測試類:
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public class Test { public static void main(String[] args) { Car car = new Car(); InvocationHandler h = new TimeHandler(car); Class<?> cls = car.getClass(); /** * newProxyInstanced的參數(shù) * 分別是:類加載器、實現(xiàn)的接口、實現(xiàn)的處理器 */ Moveable m = (Moveable) Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(),h); m.move(); } }
這樣的輸出結果是:
汽車開始行使
汽車行駛中
汽車行駛結束,行駛的時間為:137毫秒
//后面的時間是隨機產(chǎn)生的,每次都不一樣
注意:
JDK代理只能代理實現(xiàn)了接口的類,沒有實現(xiàn)接口的不能代理
以上就是JDK動態(tài)代理,當然還有cglib動態(tài)代理:
cglib是針對類來實現(xiàn)代理的,cglib的原理是對指定的目標類生成一個子類,并覆蓋其中方法實現(xiàn)增強,但因為采用的是繼承,所以不能對final修飾的類進行代理,因為小應學長自己對這一塊也沒有完全掌握,這里就不多講解,大家可以參考其他博主的技術文章。
三月份完美收官!最后小應學長十分感謝大家的支持的陪伴,你們在支持是我最大的動力,繼續(xù)寫出大家喜歡的文章!
到此這篇關于Java 深入淺出講解代理模式的文章就介紹到這了,更多相關Java 代理模式內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
JPA中@CreatedDate和@LastModifiedDate的使用方式
這篇文章主要介紹了JPA中@CreatedDate和@LastModifiedDate的使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-11-11基于springboot?配置文件context-path的坑
這篇文章主要介紹了基于springboot?配置文件context-path的坑,基于很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01