问题描述
使用动态代理的用例是什么?
它们与字节码的生成和反射有何关系?
任何建议阅读?
推荐答案
我强烈推荐此资源.
首先,您必须了解代理模式用例.请记住,代理的主要目的是控制访问 目标对象,而不是增强 目标对象.访问控件包括同步,身份验证,远程访问(RPC),懒惰实例(Hibernate,Mybatis),AOP(交易).
与静态代理相比,动态代理生成字节码,该字节码需要在运行时进行Java反射.使用动态方法,您无需创建代理类,这可能会带来更多便利.
其他推荐答案
a 动态代理类是一个实现列表的类 在运行时指定的接口,以便通过 一类实例的接口之一将被编码,并且 通过统一界面派遣到另一个对象.有可能 用于为接口列表创建类型安全的代理对象 不需要代理类的生成前.动态代理 课程对于需要提供的应用程序或库很有用 类型安全的反射性派遣在存在的对象上的调用 接口API.
其他推荐答案
我刚刚想到了一个有趣的动态代理使用.
我们遇到了一些麻烦的非关键服务,该服务与另一项依赖服务相结合,并想探索当该依赖服务变得不可用时耐心的方式.
因此,我写了一个 loadshedproxy ,该占两个代表 - 一个是"正常"服务的远程含义(JNDI查找后).另一个对象是"虚拟"负载冲洗式.每种方法都有简单的逻辑,可以在重试之前将超时并转移到假人的一定时间长度上.这是我的使用方式:
// 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; } }
问题描述
What is a use case for using a dynamic proxy?
How do they relate to bytecode generation and reflection?
Any recommended reading?
推荐答案
I highly recommend this resource.
First of all, you must understand what the proxy pattern use case. Remember that the main intent of a proxy is to control access to the target object, rather than to enhance the functionality of the target object. The access control includes synchronization, authentication, remote access (RPC), lazy instantiation (Hibernate, Mybatis), AOP (transaction).
In contrast with static proxy, the dynamic proxy generates bytecode which requires Java reflection at runtime. With the dynamic approach you don't need to create the proxy class, which can lead to more convenience.
其他推荐答案
A dynamic proxy class is a class that implements a list of interfaces specified at runtime such that a method invocation through one of the interfaces on an instance of the class will be encoded and dispatched to another object through a uniform interface. It can be used to create a type-safe proxy object for a list of interfaces without requiring pre-generation of the proxy class. Dynamic proxy classes are useful to an application or library that needs to provide type-safe reflective dispatch of invocations on objects that present interface APIs.
其他推荐答案
I just came up with an interesting use for a dynamic proxy.
We were having some trouble a non-critical service that is coupled with another dependant service and wanted to explore ways of being fault-tolerant when that dependant service becomes unavailable.
So I wrote a LoadSheddingProxy that takes two delegates - one is the remote impl for the 'normal' service (after the JNDI lookup). The other object is a 'dummy' load-shedding impl. There is simple logic surrounding each method invoke that catches timeouts and diverts to the dummy for a certain length of time before retrying. Here's how I use it:
// 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(); } } }
And here's the proxy:
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; } }