代理模式是java中最常用的設(shè)計(jì)模式之一,尤其是在spring框架中廣泛應(yīng)用。對(duì)于java的代理模式,一般可分為:靜態(tài)代理、動(dòng)態(tài)代理、以及cglib實(shí)現(xiàn)動(dòng)態(tài)代理。
對(duì)于上述三種代理模式,分別進(jìn)行說明。
1.靜態(tài)代理
靜態(tài)代理其實(shí)就是在程序運(yùn)行之前,提前寫好被代理方法的代理類,編譯后運(yùn)行。在程序運(yùn)行之前,class已經(jīng)存在。
下面我們實(shí)現(xiàn)一個(gè)靜態(tài)代理demo:
靜態(tài)代理
定義一個(gè)接口target
1
2
3
4
5
6
|
package com.test.proxy; public interface target { public string execute(); } |
targetimpl 實(shí)現(xiàn)接口target
1
2
3
4
5
6
7
8
9
10
|
package com.test.proxy; public class targetimpl implements target { @override public string execute() { system.out.println( "targetimpl execute!" ); return "execute" ; } } |
代理類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
package com.test.proxy; public class proxy implements target{ private target target; public proxy(target target) { this .target = target; } @override public string execute() { system.out.println( "perprocess" ); string result = this .target.execute(); system.out.println( "postprocess" ); return result; } } |
測(cè)試類:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
package com.test.proxy; public class proxytest { public static void main(string[] args) { target target = new targetimpl(); proxy p = new proxy(target); string result = p.execute(); system.out.println(result); } } |
運(yùn)行結(jié)果:
1
2
3
4
|
perprocess targetimpl execute! postprocess execute |
靜態(tài)代理需要針對(duì)被代理的方法提前寫好代理類,如果被代理的方法非常多則需要編寫很多代碼,因此,對(duì)于上述缺點(diǎn),通過動(dòng)態(tài)代理的方式進(jìn)行了彌補(bǔ)。
2.動(dòng)態(tài)代理
動(dòng)態(tài)代理主要是通過反射機(jī)制,在運(yùn)行時(shí)動(dòng)態(tài)生成所需代理的class.
動(dòng)態(tài)代理
接口
1
2
3
4
5
6
|
package com.test.dynamic; public interface target { public string execute(); } |
實(shí)現(xiàn)類
1
2
3
4
5
6
7
8
9
10
|
package com.test.dynamic; public class targetimpl implements target { @override public string execute() { system.out.println( "targetimpl execute!" ); return "execute" ; } } |
代理類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package com.test.dynamic; import java.lang.reflect.invocationhandler; import java.lang.reflect.method; public class dynamicproxyhandler implements invocationhandler{ private target target; public dynamicproxyhandler(target target) { this .target = target; } @override public object invoke(object proxy, method method, object[] args) throws throwable { system.out.println( "========before==========" ); object result = method.invoke(target,args); system.out.println( "========after===========" ); return result; } } |
測(cè)試類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
package com.test.dynamic; import java.lang.reflect.proxy; public class dynamicproxytest { public static void main(string[] args) { target target = new targetimpl(); dynamicproxyhandler handler = new dynamicproxyhandler(target); target proxysubject = (target) proxy.newproxyinstance(targetimpl. class .getclassloader(),targetimpl. class .getinterfaces(),handler); string result = proxysubject.execute(); system.out.println(result); } } |
運(yùn)行結(jié)果:
1
2
3
4
|
========before========== targetimpl execute! ========after=========== execute |
無論是動(dòng)態(tài)代理還是靜態(tài)帶領(lǐng),都需要定義接口,然后才能實(shí)現(xiàn)代理功能。這同樣存在局限性,因此,為了解決這個(gè)問題,出現(xiàn)了第三種代理方式:cglib代理。
3.cglib代理
cglib采用了非常底層的字節(jié)碼技術(shù),其原理是通過字節(jié)碼技術(shù)為一個(gè)類創(chuàng)建子類,并在子類中采用方法攔截的技術(shù)攔截所有父類方法的調(diào)用,順勢(shì)織入橫切邏輯。jdk動(dòng)態(tài)代理與cglib動(dòng)態(tài)代理均是實(shí)現(xiàn)spring aop的基礎(chǔ)。
cglib動(dòng)態(tài)代理
目標(biāo)類
1
2
3
4
5
6
7
8
9
10
|
package com.test.cglib; public class target { public string execute() { string message = "-----------test------------" ; system.out.println(message); return message; } } |
通用代理類:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
package com.test.cglib; import net.sf.cglib.proxy.methodinterceptor; import net.sf.cglib.proxy.methodproxy; import java.lang.reflect.method; public class mymethodinterceptor implements methodinterceptor{ @override public object intercept(object obj, method method, object[] args, methodproxy proxy) throws throwable { system.out.println( ">>>>methodinterceptor start..." ); object result = proxy.invokesuper(obj,args); system.out.println( ">>>>methodinterceptor ending..." ); return "result" ; } } |
測(cè)試類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
package com.test.cglib; import net.sf.cglib.proxy.enhancer; public class cglibtest { public static void main(string ... args) { system.out.println( "***************" ); target target = new target(); cglibtest test = new cglibtest(); target proxytarget = (target) test.createproxy(target. class ); string res = proxytarget.execute(); system.out.println(res); } public object createproxy( class targetclass) { enhancer enhancer = new enhancer(); enhancer.setsuperclass(targetclass); enhancer.setcallback( new mymethodinterceptor()); return enhancer.create(); } } |
執(zhí)行結(jié)果:
1
2
3
4
5
|
*************** >>>>methodinterceptor start... -----------test------------ >>>>methodinterceptor ending... result |
代理對(duì)象的生成過程由enhancer類實(shí)現(xiàn),大概步驟如下:
1、生成代理類class的二進(jìn)制字節(jié)碼;
2、通過class.forname加載二進(jìn)制字節(jié)碼,生成class對(duì)象;
3、通過反射機(jī)制獲取實(shí)例構(gòu)造,并初始化代理類對(duì)象。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。
原文鏈接:http://www.jianshu.com/p/37d0ac9233b9