多方法接口回调_啊?Java反射遇到接口
本文適合有點Java反射基礎的同學,在Java反射調用方法時遇到接口參數是一件很蛋疼的事情。
在反射調用方法時需要傳參數,像傳遞基本數據類型進去用就完事,傳個對象進去怎么整都沒關系,因為你在外部有對象的引用,但 如果需要你傳遞接口參數,而且這個接口類也是你反射得到的,那怎么拿到接口回調的值呢? 下面通過一個例子告訴你咋整。
場景和需求
場景:假設我是提供方A,有個業務方B,提供ID方C。
其中提供ID方C有如下代碼來提供ID。
需求是:
如果業務方B接入C(也就是存在IdManager類),那么我方需要獲得業務方B設置的Id。
如果業務方B沒有接入C(不存在IdManager類),那么我就不獲取。
基本分析
懂少許反射的同學肯定認為這太簡單了,思路如下:
開始擼代碼
public class Main { public static void main(String[] args) { // 模擬接入方B已經傳入id IdManager.getInstance().setId("MyId:10086!"); // 我們的代碼 try { // 1. 找不到就catch住拋出的異常(對應第二種未接入的情況) Class<?> idManagerClazz = Class.forName("com.grcen.proxy.IdManager"); // 2. 獲取Callback類型 Class<?> callbackClazz = Class.forName("com.grcen.proxy.Callback"); // 3. 找到getInstance方法 Method getInstance = idManagerClazz.getMethod("getInstance"); // 4.將獲取到的Callback類型用來找到getId方法 Method getId = idManagerClazz.getMethod("getId", callbackClazz); // 執行getInstance方法獲取到單例對象(參數1:執行該方法的對象。參數2:該方法的參數) Object instance = getInstance.invoke(null, null); // 利用instance對象執行getId方法獲取ID!! // getId.invoke(instance,????) -> ???該方法的參數是接口該怎么傳呢?? } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { // 這里默認處理異常(正式代碼別這樣搞) e.printStackTrace(); } }}寫到上面出現問號的地方就尷尬了,因為在IdManager類中是通過接口參數來回調id值的。那理所當然我們應該傳入應該接口參數,但在該場景下并不知道有沒有Callback類,是沒法聲明接口的。即使找到callbackClazz調用newInstance()來創建對象,那請問怎么知道回調結果啊?而且只能實現接口不能實例化接口。
使用代理
代理顧名思義找個中間商實現接口,在實現的方法中即可拿到回調值。在Java中提供了InvocationHandler接口實現代理。InvocationHandler意為調用處理者。目的很明確:找個類實現我反射拿到的接口,在實現的方法中拿到回調的值。
創建MyHandler類實現InvocationHandler接口
public class MyHandler implements InvocationHandler { /** * 參數說明:這些參數先知道是個什么意思 * @param proxy 所代理的那個真實對象 * @param method 我們所要調用真實對象的某個方法的Method對象 * @param args 調用真實對象某個方法時接受的參數 * @return 代理執行完方法所返回的對象 * @throws Throwable 執行過程拋出的各種異常 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 這里什么也不干就打印回調的值 System.out.println(args[0]); return null; }}利用Proxy類關聯Callback接口和MyHandler
// Main類完整代碼public class Main { public static void main(String[] args) { // 模擬接入方已經傳入id IdManager.getInstance().setId("MyId:10086!"); // 我們的代碼 try { Class<?> idManagerClazz = Class.forName("com.grcen.proxy.IdManager"); Class<?> callbackClazz = Class.forName("com.grcen.proxy.Callback"); Method getInstance = idManagerClazz.getMethod("getInstance"); Method getId = idManagerClazz.getMethod("getId", callbackClazz); Object instance = getInstance.invoke(null, null); // 新增代碼 MyHandler myHandler = new MyHandler(); // 參數說明在下文 Object myCallback = Proxy.newProxyInstance( Main.class.getClassLoader(), new Class[]{callbackClazz}, myHandler); getId.invoke(instance, myCallback); } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } }}Proxy.newProxyInstance()的參數有:(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
先來看看代碼運行結果:
再梳理下主要過程,先從getId.invoke(instance,myCallback)來看,執行getId方法,傳入執行對象instance,方法所需參數myCallback。然后在getId方法中回調接口,因為myCallback是個代理,它的接口實現在MyHandler,所以最后回調執行的是MyHandler中的invoke方法。前面大致羅列了invoke方法的參數意思,我們來驗證一下。
// MyHandlerpublic class MyHandler implements InvocationHandler { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("invoke參數2真實代理對象所調用的方法" + method); System.out.println("invoke參數3調用方法的傳入參數為:" + args[0]); // 此處已知只有一個參數 return null; }}結果:
注意:
原文鏈接:
https://blog.csdn.net/qq_40883985/article/details/96633773
總結
以上是生活随笔為你收集整理的多方法接口回调_啊?Java反射遇到接口的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 幼儿园老师锦旗赠言感谢语大全414条
- 下一篇: 手机如何访问电脑局域网(手机如何访问电脑