回答
類java.lang.reflect.Proxy
允許您通過處理InvocationHandler
中的方法調用來動態實現接口。它被認爲是Java的反射工具的一部分,但與字節碼生成無關。
關於使用Proxy類,Sun有a tutorial。 Google helps, too.
一個用例是hibernate--它爲您提供了實現您的模型類接口的對象,但是在getters和setters下面存在與db相關的代碼。即你使用它們就好像它們只是簡單的POJO一樣,但實際上有很多事情正在掩蓋之中。
例如 - 你只需調用lazily加載的屬性的getter,但真正的屬性(可能是整個大對象結構)從數據庫中獲取。
您應該檢查cglib庫以獲取更多信息。
甲動態代理類是實現在運行時指定的 接口的列表,使得通過對類的一個實例的接口 一個將被編碼和 方法調用調度到另一個類通過統一的界面對象。它可以是 ,用於爲接口列表創建類型安全的代理對象 ,無需預先生成代理類。動態代理 類對於需要提供 類型安全的對調用接口API的對象的反射調度的應用程序或庫很有用。
好的答案,這個事情的一個很好的例子是Spring Remoting,它內置了HTTP,RMI,EJB和JMS的代理功能。 – Robin 2009-06-01 13:39:53
我只是想出了一個動態代理一個有趣的使用。
我們遇到了一些與非關鍵服務相關的服務,這些服務與另一個相關服務結合在一起,並且希望探索在相關服務不可用時的容錯方式。
所以我寫了一個LoadSheddingProxy需要兩個代表 - 一個是'正常'服務的遠程impl(在JNDI查找之後)。另一個對象是一個「虛擬」卸載impl。圍繞每個方法調用的簡單邏輯可以捕獲超時並在重試之前轉向虛擬機一段時間。下面是我如何使用它:
// This is part of your ServiceLocator class
public static MyServiceInterface getMyService() throws Exception
{
MyServiceInterface loadShedder = new MyServiceInterface() {
public Thingy[] getThingys(Stuff[] whatever) throws Exception {
return new Thingy[0];
}
//... etc - basically a dummy version of your service goes here
}
Context ctx = JndiUtil.getJNDIContext(MY_CLUSTER);
try {
MyServiceInterface impl = ((MyServiceHome) PortableRemoteObject.narrow(
ctx.lookup(MyServiceHome.JNDI_NAME),
MyServiceHome.class)).create();
// Here's where the proxy comes in
return (MyService) Proxy.newProxyInstance(
MyServiceHome.class.getClassLoader(),
new Class[] { MyServiceInterface.class },
new LoadSheddingProxy(MyServiceHome.JNDI_NAME, impl, loadShedder, 60000)); // 10 minute retry
} catch (RemoteException e) { // If we can't even look up the service we can fail by shedding load too
logger.warn("Shedding load");
return loadShedder;
} finally {
if (ctx != null) {
ctx.close();
}
}
}
而這裏的代理:
public class LoadSheddingProxy implements InvocationHandler {
static final Logger logger = ApplicationLogger.getLogger(LoadSheddingProxy.class);
Object primaryImpl, loadDumpingImpl;
long retry;
String serviceName;
// map is static because we may have many instances of a proxy around repeatedly looked-up remote objects
static final Map<String, Long> servicesLastTimedOut = new HashMap<String, Long>();
public LoadSheddingProxy(String serviceName, Object primaryImpl, Object loadDumpingImpl, long retry)
{
this.serviceName = serviceName;
this.primaryImpl = primaryImpl;
this.loadDumpingImpl = loadDumpingImpl;
this.retry = retry;
}
public Object invoke(Object obj, Method m, Object[] args) throws Throwable
{
try
{
if (!servicesLastTimedOut.containsKey(serviceName) || timeToRetry()) {
Object ret = m.invoke(primaryImpl, args);
servicesLastTimedOut.remove(serviceName);
return ret;
}
return m.invoke(loadDumpingImpl, args);
}
catch (InvocationTargetException e)
{
Throwable targetException = e.getTargetException();
// DETECT TIMEOUT HERE SOMEHOW - not sure this is the way to do it???
if (targetException instanceof RemoteException) {
servicesLastTimedOut.put(serviceName, Long.valueOf(System.currentTimeMillis()));
}
throw targetException;
}
}
private boolean timeToRetry() {
long lastFailedAt = servicesLastTimedOut.get(serviceName).longValue();
return (System.currentTimeMillis() - lastFailedAt) > retry;
}
}
好的解釋在這裏https://opencredo.com/dynamic-proxies-java/ – Bala 2016-06-28 13:41:37