Java的動(dòng)態(tài)代理和靜態(tài)代理及反射常用API詳解
JDK動(dòng)態(tài)代理
我們看下JDK動(dòng)態(tài)代理的實(shí)現(xiàn)步驟:
第一步:創(chuàng)建接口,JDK動(dòng)態(tài)代理基于接口實(shí)現(xiàn),所以接口必不可少(準(zhǔn)備工作)
第二步:實(shí)現(xiàn)InvocationHandler接口,重寫invoke方法(準(zhǔn)備工作)
第三步:調(diào)用Proxy的靜態(tài)方法newProxyInstance方法生成代理實(shí)例(生成實(shí)例時(shí)需要提供類加載器,我們可以使用接口類的加載器即可)
第四步:使用新生成的代理實(shí)例調(diào)用某個(gè)方法實(shí)現(xiàn)功能。
我們的動(dòng)態(tài)代理實(shí)現(xiàn)過(guò)程中根本沒(méi)有涉及到真實(shí)類實(shí)例。
靜態(tài)代理
package ceshi1; public interface Iuser { void eat(String s); }
package ceshi1; public class UserImpl implements Iuser { @Override public void eat(String s) { System.out.println("我要吃"+s); } }
package ceshi1; public class UserProxy implements Iuser { private Iuser user = new UserImpl(); @Override public void eat(String s) { System.out.println("靜態(tài)代理前置內(nèi)容"); user.eat(s); System.out.println("靜態(tài)代理后置內(nèi)容"); } }
package ceshi1; public class ProxyTest { public static void main(String[] args) { UserProxy proxy = new UserProxy(); proxy.eat("蘋果"); } }
動(dòng)態(tài)代理
package ceshi1; public interface Iuser { void eat(String s); }
package ceshi1; public class UserImpl implements Iuser { @Override public void eat(String s) { System.out.println("我要吃"+s); } }
package ceshi1; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class DynamicProxy implements InvocationHandler { private Object object;//用于接收具體實(shí)現(xiàn)類的實(shí)例對(duì)象 //使用帶參數(shù)的構(gòu)造器來(lái)傳遞具體實(shí)現(xiàn)類的對(duì)象 public DynamicProxy(Object obj){ this.object = obj; } @Override public Object invoke(Object proxy, Method method, Object[] args)throws Throwable { System.out.println("前置內(nèi)容"); method.invoke(object, args); System.out.println("后置內(nèi)容"); return null; } }
package ceshi1; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public class ProxyTest { public static void main(String[] args) { Iuser user = new UserImpl(); InvocationHandler h = new DynamicProxy(user); Iuser proxy = (Iuser) Proxy.newProxyInstance(Iuser.class.getClassLoader(), new Class[]{Iuser.class}, h); proxy.eat("蘋果"); } }
反射
JDK 提供的反射 API 進(jìn)行反射調(diào)用:
Class clz = Class.forName("com.chenshuyi.reflect.Apple"); Method method = clz.getMethod("setPrice", int.class); Constructor constructor = clz.getConstructor(); Object object = constructor.newInstance(); method.invoke(object, 4);
一般情況下我們使用反射獲取一個(gè)對(duì)象的步驟:
獲取類的 Class 對(duì)象實(shí)例
Class clz = Class.forName("com.zhenai.api.Apple");
根據(jù) Class 對(duì)象實(shí)例獲取 Constructor 對(duì)象
Constructor appleConstructor = clz.getConstructor();
使用 Constructor 對(duì)象的 newInstance 方法獲取反射類對(duì)象
Object appleObj = appleConstructor.newInstance();
而如果要調(diào)用某一個(gè)方法,則需要經(jīng)過(guò)下面的步驟:
獲取方法的 Method 對(duì)象
Method setPriceMethod = clz.getMethod("setPrice", int.class);
利用 invoke 方法調(diào)用方法
setPriceMethod.invoke(appleObj, 14);
反射常用API
在 Java API 中,獲取 Class 類對(duì)象有三種方法:
第一種,使用 Class.forName 靜態(tài)方法。當(dāng)你知道該類的全路徑名時(shí),你可以使用該方法獲取 Class 類對(duì)象。
Class clz = Class.forName("java.lang.String");
第二種,使用 .class 方法。
這種方法只適合在編譯前就知道操作的 Class。
Class clz = String.class;
第三種,使用類對(duì)象的 getClass() 方法。
String str = new String("Hello"); Class clz = str.getClass();
通過(guò)反射創(chuàng)建類對(duì)象
通過(guò)反射創(chuàng)建類對(duì)象主要有兩種方式:通過(guò) Class 對(duì)象的 newInstance() 方法、通過(guò) Constructor 對(duì)象的 newInstance() 方法。
第一種:通過(guò) Class 對(duì)象的 newInstance() 方法。
Class clz = Apple.class; Apple apple = (Apple)clz.newInstance();
第二種:通過(guò) Constructor 對(duì)象的 newInstance() 方法
Class clz = Apple.class; Constructor constructor = clz.getConstructor(); Apple apple = (Apple)constructor.newInstance();
通過(guò) Constructor 對(duì)象創(chuàng)建類對(duì)象可以選擇特定構(gòu)造方法,而通過(guò) Class 對(duì)象則只能使用默認(rèn)的無(wú)參數(shù)構(gòu)造方法。下面的代碼就調(diào)用了一個(gè)有參數(shù)的構(gòu)造方法進(jìn)行了類對(duì)象的初始化。
Class clz = Apple.class; Constructor constructor = clz.getConstructor(String.class, int.class); Apple apple = (Apple)constructor.newInstance("紅富士", 15);
我們通過(guò) Class 對(duì)象的 getFields() 方法可以獲取 Class 類的屬性,但無(wú)法獲取私有屬性。
Class clz = Apple.class; Field[] fields = clz.getFields(); for (Field field : fields) { System.out.println(field.getName()); }
而如果使用 Class 對(duì)象的 getDeclaredFields() 方法則可以獲取包括私有屬性在內(nèi)的所有屬性:
Class clz = Apple.class; Field[] fields = clz.getDeclaredFields(); for (Field field : fields) { System.out.println(field.getName()); }
到此這篇關(guān)于Java的動(dòng)態(tài)代理和靜態(tài)代理及反射常用API詳解的文章就介紹到這了,更多相關(guān)Java動(dòng)態(tài)代理和反射內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MyBatis注解方式之@Update/@Delete使用詳解
這篇文章主要介紹了MyBatis注解方式之@Update/@Delete使用詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-11-11Spring Cloud Feign實(shí)例講解學(xué)習(xí)
這篇文章主要介紹了Spring Cloud Feign實(shí)例講解學(xué)習(xí),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-02-02深入理解JVM之Java對(duì)象的創(chuàng)建、內(nèi)存布局、訪問(wèn)定位詳解
這篇文章主要介紹了深入理解JVM之Java對(duì)象的創(chuàng)建、內(nèi)存布局、訪問(wèn)定位,結(jié)合實(shí)例形式詳細(xì)分析了Java對(duì)象的創(chuàng)建、內(nèi)存布局、訪問(wèn)定位相關(guān)概念、原理、操作技巧與注意事項(xiàng),需要的朋友可以參考下2019-09-09Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(17)
下面小編就為大家?guī)?lái)一篇Java基礎(chǔ)的幾道練習(xí)題(分享)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧,希望可以幫到你2021-07-07springboot3.x版本集成log4j遇到Logging?system?failed?to?initial
使用Springboot?3.x集成Log4j時(shí)可能會(huì)遇到版本沖突的問(wèn)題,這通??梢酝ㄟ^(guò)檢查Maven依賴樹來(lái)識(shí)別,一旦發(fā)現(xiàn)沖突,將Log4j的版本統(tǒng)一更新到最新的兼容版本,例如2.21.1,即可解決問(wèn)題,此方法有效解決了日志打印錯(cuò)誤,是處理類似問(wèn)題的一個(gè)實(shí)用參考2024-09-09java實(shí)現(xiàn)從網(wǎng)絡(luò)下載多個(gè)文件
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)從網(wǎng)絡(luò)下載多個(gè)文件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07mybatis-plus報(bào)錯(cuò)net.sf.jsqlparser.statement.select.SelectBody的
本文主要介紹了mybatis-plus報(bào)錯(cuò)net.sf.jsqlparser.statement.select.SelectBody的問(wèn)題解決,具有一定的參考價(jià)值,感興趣的可以了解一下2024-08-08java實(shí)現(xiàn)把一個(gè)List集合拆分成多個(gè)的操作
這篇文章主要介紹了java實(shí)現(xiàn)把一個(gè)List集合拆分成多個(gè)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08SpringBoot Pom文件依賴及Starter啟動(dòng)器詳細(xì)介紹
這篇文章主要介紹了SpringBoot Pom文件的依賴與starter啟動(dòng)器的作用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-09-09