反射機制
java語言提供的一種基礎(chǔ)功能,通過反射,我們可以操作這個類或?qū)ο螅热绔@取這個類中的方法、屬性和構(gòu)造方法等。
動態(tài)代理:分為jdk動態(tài)代理、cglib動態(tài)代理(spring中的動態(tài)代理)。
靜態(tài)代理
預(yù)先(編譯期間)確定了代理者與被代理者之間的關(guān)系,也就是說,若代理類在程序運行前就已經(jīng)存在了,這種情況就叫靜態(tài)代理
動態(tài)代理
代理類在程序運行時創(chuàng)建的代理方式。也就是說,代理類并不是在java代碼中定義的,而是在運行期間根據(jù)我們在java代碼中的“指示”動態(tài)生成的。
動態(tài)代理比靜態(tài)代理的優(yōu)勢在于:
動態(tài)代理可以很方便的對代理類的函數(shù)進行統(tǒng)一的處理(invoke),而不是修改每個代理類的函數(shù),更靈活和擴展。
jdk的動態(tài)代理(依賴于接口)
在java的動態(tài)代理機制中,有兩個重要的類或接口,一個是invocationhandler接口,另一個是proxy類。
invocationhandler接口是給動態(tài)代理類實現(xiàn)的,負(fù)責(zé)處理被代理對象的操作
proxy類是用來創(chuàng)建動態(tài)代理類實例對象的,只有得到這個對象,才能調(diào)用需要代理的方法。
動態(tài)代理的代理類是在靜態(tài)代理類上進行修改,將動態(tài)代理類實現(xiàn)invocationhandler接口,java電子書重寫invoke方法,invoke方法通過傳入的被代理類方法和參數(shù)來執(zhí)行。
如下實例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
public interface appservice { void createapp(string name); void deleteapp(string name); } //代理類(比如微商代理) public class appserviceimpl implements appservice{ @override public void createapp(string name) { system.out.print( "app[" +name+ "] has been created." ); } @override public void deleteapp(string name) { system.out.print( "app[" +name+ "] has been delete." ); } } import java.lang.reflect.invocationhandler; import java.lang.reflect.method; public class loggerinterceptor implements invocationhandler { private object target; //委托類(被代理類)的實例,比如廠家 public loggerinterceptor(object target){ this .target = target; } @override public object invoke(object proxy, method method, object[] args) throws throwable { system.out.println( "entered " +target.getclass().getname()+ "-" +method.getname()+ ",with arguments{" +args[ 0 ]+ "}" ); object result = method.invoke(target, args); //調(diào)用目標(biāo)對象的方法 (調(diào)用廠家的方法(createapp)及參數(shù)(kevin test)) system.out.println( "before return:" +result); return result; } } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
import java.lang.reflect.proxy; public class test { public static void main(string[] args) { appservice target = new appserviceimpl(); //生成目標(biāo)對象 (代理類的對象) //接下來創(chuàng)建代理對象 appservice proxy = (appservice) proxy.newproxyinstance( target.getclass().getclassloader(), target.getclass().getinterfaces(), new loggerinterceptor(target)); proxy.createapp( "kevin test1" ); proxy.deleteapp( "kevin test2" ); } } /** * 1、jdk的動態(tài)代理實現(xiàn)方式是依賴于接口的,首先使用接口來定義好操作規(guī)范。 * 2、通過proxy類產(chǎn)生的代理對象調(diào)用被代理對象的操作。 * 3、而這個操作又被分發(fā)給invocationhandler接口的invoke方法具體執(zhí)行 * * 在java的動態(tài)代理機制中,有兩個重要的類或接口,一個是invocationhandler接口、另一個則是 proxy類,這個類和接口是實現(xiàn)我們動態(tài)代理所必須用到的。 invocationhandler接口是給動態(tài)代理類實現(xiàn)的,負(fù)責(zé)處理被代理對象的操作的,而proxy是用來創(chuàng)建動態(tài)代理類實例對象的,因為只有得到了這個對象我們才能調(diào)用那些需要代理的方法。 * * 此方法的參數(shù)含義如下 proxy:代表動態(tài)代理對象 method:代表正在執(zhí)行的方法 args:代表當(dāng)前執(zhí)行方法傳入的實參 返回值:表示當(dāng)前執(zhí)行方法的返回值 * * 如上: * 使用了proxy類的newproxyinstance方法生成代理對象,然后用這個對象去調(diào)用createapp()和deleteapp()方法, * 其實系統(tǒng)會將這2個方法分發(fā)給invoke()方法區(qū)執(zhí)行。其中proxy對象的類是系統(tǒng)幫我們動態(tài)創(chuàng)建了,其實實現(xiàn)了我們的業(yè)務(wù)接口appservice * */ |
cglib動態(tài)代理(繼承方式)
cglib動態(tài)代理中使用methodinterceptor來實現(xiàn)動態(tài)代理類。
攔截器methodinterceptor中就是由methodproxy的invoksuper方法調(diào)用代理方法的。
methodproxy類生成代理方法和代理方法的簽名。
jdk動態(tài)代理和cglib動態(tài)代理的區(qū)別:
1、jdk動態(tài)代理是實現(xiàn)了被代理對象的接口,cglib是繼承了被代理對象。
2、cglib因為是繼承機制,所以無法代理被final修飾的方法。
3、jdk和cglib都是在運行期間生產(chǎn)字節(jié)碼,jdk是直接寫class字節(jié)碼,cglib使用asm框架寫class字節(jié)碼;cglib代理實現(xiàn)更復(fù)雜,生成代理類比jdk效率低。
4、jdk調(diào)用代理方法,是通過反射實現(xiàn)機制調(diào)用,cglib是通過fashclass機制直接調(diào)用方法,效率更高。
fastcalss機制:
為代理類和被代理類個生成一個class,這個class會為代理類或被代理類的方法分配一個index。
這個index當(dāng)做一個入?yún)ⅲ琭ashclass就可以直接定位要調(diào)用的方法,并直接進行調(diào)用。這樣省去了反射調(diào)用,所以效率高。