2017-01-11 118 views
1

是否有可能通過Java反射子類檢索的類?我試圖改變一個已經加載類的方法的實現。我知道沒有辦法通過常規反射方法來做到這一點。但我想知道是否有可能通過繼承獲取類,如:是否有可能通過Java反射子類檢索的類

final Class cls = classLoader.loadClass(className); 
Object newRemoteInstance = new cls() { 
    @Override 
    public void saySth() { 
     System.out.println("changed"); 
    } 
} 

,而不是獲取與

cls.newInstance(); 

完全一樣的執行,然後複製已加載的類的字段成新創建的實例,並進一步使用這個新實例,而不是已經加載的實例。要更改的類不可用,所以我必須使用反射。

在此先感謝。

回答

1

在你的問題中,你不清楚什麼是擴展,你需要爲此使用反射。因爲你可以通過反射創建你的實例,然後簡單地將它包裝到代理或裝飾器中,以增強或改變它的行爲。

class MyFactory { 
    MyClass create() { 
     return MyDecorator(cls.newInstance()); 
    } 
} 

MyDecorator實現了一樣的公共接口,當然MyClass

但是,如果您真的需要通過反射來做到這一點,我知道有幾種可能的方法可能會起作用,具體取決於您的想法。

使用Java代理

如果您在問題的方法來自於一個界面,你可以使用Java Proxy改變其行爲。

OrderService subject = new DefaultOrderService(); 
OrderService orderService = (OrderService) Proxy.newProxyInstance(
     this.getClass().getClassLoader(), 
      new Class<?>[]{OrderService.class}, 
      (proxy, method, args) -> { 
       try { 
        System.out.println("Before method"); 
        return method.invoke(subject, args); 
       } 
       finally { 
        System.out.println("After method"); 
       } 
      } 
     ); 
System.out.println(orderService.getClass()); 
orderService.getOrder(10); 

上述收益率有點像這樣的類名的輸出:com.sun.proxy.$Proxy24.class爲類代理的。

使用Java CGLIB

但是,如果你被迫使用普通類,而不是一個接口,那麼你可以使用庫像cglib代替。

代理包含從原始類繼承(即DefaultOrderService)。這有一個好處;它不需要所討論的類實現一個接口,以便能夠創建代理,這在你的問題中似乎就是這種情況。

DefaultOrderService subject = new DefaultOrderService(); 
Enhancer enhancer = new Enhancer(); 
enhancer.setSuperclass(DefaultOrderService.class); 
enhancer.setCallback((InvocationHandler) (obj, method, args) -> { 
    try { 
     System.out.println("Before method"); 
     return method.invoke(subject, args); 
    } 
    finally { 
     System.out.println("After method"); 
    } 
}); 

OrderService orderService = (OrderService) enhancer.create(); 
System.out.println(orderService.getClass()); 
orderService.getOrder(10); 

上面的輸出產生的結果有點像DefaultOrderService$$EnhancerByCGLIB$$9017bdba.class作爲增強對象的類。

但是,這兩個示例都是關於定義一個與另一個接口具有相同接口的新類,它們不會更改原始父類或接口。

+0

你最後的例子正是我需要的謝謝你!不幸的是,它不適用於Android(我的項目基於此),因爲CGlib生成Java字節碼,而Android則運行Dalvik字節碼。您是否知道Android的替代方案提供了相同的功能?編輯:我實際上只是發現http:// bytebuddy。網絡/並將看看它作爲聲稱支持Android的最新版本 – Phoebus

相關問題