刘欣《码农翻身》之动态代理读后感
很生動地通過故事講明白了Java動態(tài)代理這么個事,很棒:
為什么需要動態(tài)代理:人們希望在運(yùn)行時動態(tài)修改類,但是,Java一個類一旦被裝入方法區(qū),就沒法動態(tài)修改已經(jīng)編譯好的類了
解決方案:已經(jīng)被加載或者正在運(yùn)行的類既然不能被修改,就需要運(yùn)行時動態(tài)生成一個代理類,達(dá)到“運(yùn)行時動態(tài)修改類”的目的。
代理類是基于原來的類生成的新的類,具有運(yùn)行時需要的功能,比如日志記錄、事務(wù)支持、權(quán)限控制等。
如何實(shí)現(xiàn)功能的動態(tài)添加:
在看head first in Java時,有講過接口的使用原則,符合has-a關(guān)系時使用接口,像是一個,當(dāng)需要使用行為時使用接口,比如我想使用鋼琴的發(fā)聲功能,那我只需要實(shí)現(xiàn)鋼琴的接口,接口里面有發(fā)聲的功能,我是個人,我可以借助鋼琴的接口發(fā)出鋼琴的聲音,但我不是鋼琴,我是人。OK
所以在運(yùn)行時需要動態(tài)添加的行為都可以認(rèn)為是has-a關(guān)系,這樣,新的類通過代理接口,就可以具有想要的功能了,下面詳細(xì)說說代理接口:
public interface IHelloWorld{public void sayHello(); } public class HelloWorld implements IHelloWorld{public void sayHello(){System.out.println("hello world!");} }現(xiàn)在是要在方法層面,給代理接口里的方法里添加功能,如何做這么細(xì)粒度的動態(tài)功能增強(qiáng)呢?(也可以說是織入,這個詞,在國內(nèi)是瘋狂軟件的李剛老師第一個提出來的,老師就真的很強(qiáng),向走在前面的探路人,偉大的前輩們致敬!)
如何給代理接口中的這個目標(biāo)方法,添加想要的功能呢?必須通過實(shí)現(xiàn)InvocationHandler接口,那么我們來看看這個接口里面有什么:
只有一個方法invoke!通過這個接口里的方法,寫你需要動態(tài)增強(qiáng)的功能,比如日志記錄等等。invoke中文:調(diào)用、引用,也就是說這個接口的功能,就是讓你在運(yùn)行期間動態(tài)增強(qiáng)時調(diào)用這個方法來代替原來的方法,達(dá)到在原方法基礎(chǔ)上功能增強(qiáng)的目的。
public class LoggerHandler implements InvocationHandler {private Object target;public LoggerHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 要增強(qiáng)的功能Logger.startLog();// 原來的方法Object result = method.invoke(target, args);// 要增強(qiáng)的功能Logger.endLog();return result;}}說說LoggerHandler,英文:處理日志記錄的人,那么他就負(fù)責(zé)記錄日志,代理類會調(diào)用它,并把真正的目標(biāo)方法傳給他(method變量)讓他為目標(biāo)方法添加日志記錄的功能!
用Proxy.newProxyInstance(...)生成動態(tài)代理的類,這個類的代理方法(目標(biāo)方法),包含了增強(qiáng)的功能!
IHelloWorld hw = new HelloWorld(); LoggerHandler handler = new LoggerHandler(hw); IHelloWorld proxy = (IHelloWorld) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),hw.getClass().getInterface(),handler); proxy.sayHello();所以運(yùn)行時其實(shí)是動態(tài)生成了代理類,并調(diào)用了LoggerHandler的invoke方法實(shí)現(xiàn)功能增強(qiáng)。
所以用面向?qū)ο蟮姆绞剿伎紕討B(tài)代理?,總結(jié)下來就是:
我們要為一個對象的行為添加一個動作,比如啪啪啪前帶套套的動作,此時我們需要把啪啪啪這個動作抽象出來,創(chuàng)建一個另我(代理對象),讓全新的我實(shí)現(xiàn)這個啪啪啪的接口來執(zhí)行啪啪啪動作,然后創(chuàng)建一個另一半,她擁有帶套套的功能,它通過實(shí)現(xiàn)InvocationHandler接口,擁有invoke的功能,在這個功能里,可以設(shè)計(jì)她如何為我?guī)滋?#xff0c;同時又可以擁有和我啪啪啪的行為(我把啪啪啪的method變量傳遞給她)。之后我在啪啪啪的時候(運(yùn)行時),通過啪啪啪行為(面向接口編程)創(chuàng)建出來的全新的我,會把會帶套套和我啪啪的另一半也融合進(jìn)來,再調(diào)用啪啪啪行為時,就會有另一半為我?guī)滋住?shí)現(xiàn)了啪啪啪時才帶套(運(yùn)行時動態(tài)增加行為),而不是妹子還沒約到就開始自己帶套!
總結(jié)
以上是生活随笔為你收集整理的刘欣《码农翻身》之动态代理读后感的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 1039 数的划分
- 下一篇: vue项目中实现输入框防抖功能