在開始為Spring做記錄之前,我把之前學(xué)代理的筆記整理一番畏鼓,方便寫AOP的時(shí)候拿出來(lái)看看酱酬。
首先搞懂什么是代理,誰(shuí)代理誰(shuí)云矫,誰(shuí)又被誰(shuí)代理膳沽;然后清楚代理的目的,代理的好處让禀。這是我的方向挑社。
簡(jiǎn)單點(diǎn)說(shuō):當(dāng)對(duì)象a需要和對(duì)象b合作時(shí),b可能不太方便直接與a碰面(更多的是為了解耦巡揍,或者為了保護(hù)b)痛阻。這時(shí)候就出現(xiàn)了對(duì)象c,它是對(duì)象b的代理腮敌,由c和a直接打交道阱当。
注意三點(diǎn):
- a可以不知道b的存在
- 干實(shí)事的是b
- c可以在b做事前后調(diào)用自己的方法
ps:代理對(duì)象一般要和被代理對(duì)象實(shí)現(xiàn)同一個(gè)接口,為了保證行為的一致性糜工。
靜態(tài)代理
先貼出代碼:
public class WangPoStatic implements KindWomen{
private String name = "王婆";
private KindWomen kindWomen;
public WangPoStatic(KindWomen kindWomen) {
this.kindWomen = kindWomen;
}
public void makeEyesToMen() {
getMoneyFromMen();
kindWomen.makeEyesToMen();
dealWithLastThing();
}
@Override
public void happyWithMen() {
getMoneyFromMen();
kindWomen.happyWithMen();
dealWithLastThing();
}
//代理類動(dòng)作
private void getMoneyFromMen() {
System.out.println(name + "收好處了弊添。。捌木。");
}
private void dealWithLastThing() {
System.out.println(name + "善后了油坝。。钮莲。");
}
}
很明顯了免钻,通過(guò)構(gòu)造方法注入的就是真實(shí)對(duì)象,當(dāng)通過(guò)代理類調(diào)用公共接口中的方法時(shí)崔拥,真正干活的是真實(shí)對(duì)象极舔,只是被隱藏起來(lái)了。
動(dòng)態(tài)代理
上面的靜態(tài)代理就可以搞明白了我們?cè)鹊囊蓡?wèn)链瓦。即代理類在委托類(真實(shí)對(duì)象)執(zhí)行前后進(jìn)行自己的操作拆魏。但是靜態(tài)代理并不能滿足開發(fā)人員的要求盯桦,原因是若是公共接口有很多方法呢?那豈不是每個(gè)方法都要手動(dòng)操作一番渤刃?
這里介紹JDK中的一種動(dòng)態(tài)代理方式拥峦,這種代理方式能在運(yùn)行期間動(dòng)態(tài)地創(chuàng)建代理對(duì)象。
實(shí)現(xiàn)步驟:
i:創(chuàng)建實(shí)現(xiàn)接口InvocationHandler的類卖子,作為調(diào)用處理器略号;
ii:創(chuàng)建被代理的類以及接口;
iii:通過(guò)Proxy的靜態(tài)方法創(chuàng)建一個(gè)代理
newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
iV: 通過(guò)代理調(diào)用方法
貼出部分代碼:
// 實(shí)現(xiàn)了 InvocationHandler 接口的處理器
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//第一個(gè)參數(shù)是代理對(duì)象洋闽,第二個(gè)是被調(diào)用的方法對(duì)象玄柠,第三個(gè)是方法對(duì)象執(zhí)行invoke時(shí)需要的參數(shù)
getMoneyFromMen();
Object object = method.invoke(kw, args); //kw 為委托對(duì)象
dealWithLastThing();
return object;
}
//test方法
KindWomen kinWomen = new PanJinlian(); //真實(shí)對(duì)象 (根據(jù)真實(shí)對(duì)象 創(chuàng)建不同的代理對(duì)象)
//創(chuàng)建代理對(duì)象
KindWomen proxyKw = null;
WangPoDyn wpd = new WangPoDyn(kinWomen);
Object proxyInstance = Proxy.newProxyInstance(KindWomen.class.getClassLoader(), Ruhua.class.getInterfaces(), wpd);
if(proxyInstance != null && proxyInstance instanceof KindWomen) {
proxyKw = (KindWomen) proxyInstance;
}
proxyKw.makeEyesToMen();
System.out.println("******************");
proxyKw.happyWithMen();
代理對(duì)象調(diào)用方法時(shí)會(huì)回到調(diào)用處理器的invoke()方法里面。這個(gè)處理器對(duì)象中的invoke方法可以分為兩部分:一部分是 method.invoke(obj, args) 即真實(shí)對(duì)象干活诫舅,另一部分是在其前后執(zhí)行的其它方法羽利,在AOP中叫做連接點(diǎn)。