java动态代理与常规代理的有用性

Joh*_*erg 14 java proxy design-patterns use-case dynamic-proxy

我需要一些建议,动态代理比常规代理更有用.

我已经投入了大量精力来学习如何有效地使用动态代理.在这个问题中,抛开像AspectJ这样的框架基本上可以执行我们尝试使用动态代理实现的所有内容,或者例如CGLIB可以用来解决动态代理的一些缺点.

用例

  • 装饰器 - 例如,执行方法调用的日志记录,或缓存复杂操作的返回值
  • 坚持合同 - 即确保参数在可接受的范围内,并且返回类型符合可接受的值.
  • 适配器 - 在某个地方看到一些巧妙的文章,描述它是如何有用的.我很少遇到这种设计模式.

是其他人吗?

动态代理优势

  • 装饰器:记录所有方法调用,例如,

public Object invoke(Object target, Method method, Object[] arguments) {
         System.out.println("before method " + method.getName());
         return method.invoke(obj, args);
     }
}
Run Code Online (Sandbox Code Playgroud)

装饰器模式肯定是有用的,因为它允许所有代理方法的副作用(尽管这种行为是书籍 - 使用方面的例子..).

  • 合同:与常规代理相比,我们不需要实现完整的接口.例如,

public Object invoke(Object target, Method method, Object[] arguments) {
     if ("getValues".equals(method.getName()) {
         // check or transform parameters and/or return types, e.g., 
         return RangeUtils.validateResponse( method.invoke(obj, args) );
     }

     if ("getVersion".equals(method.getName()) {
         // another example with no delegation
         return 3;
     }
} 
Run Code Online (Sandbox Code Playgroud)

另一方面,合同只能避免实现完整接口的需要.然后,重构代理方法将无声地使动态代理无效.

结论

所以我在这里看到的是一个真实的用例,一个有问题的用例.你怎么看?

Ant*_*ric 12

除了您所描述的内容之外,动态代理还有许多潜在用途 -

  1. 事件发布 - 在方法x()上,透明地调用y()或发送消息z.
  2. 事务管理(用于数据库连接或其他事务操作)
  3. 线程管理 - 透明地解决昂贵的操作.
  4. 性能跟踪 - 例如,由CountdownLatch检查的定时操作.
  5. 连接管理 - 考虑像Salesforce的Enterprise API这样的API,要求其服务的客户端在执行任何操作之前启动会话.
  6. 更改方法参数 - 如果您想要传递空值的默认值,如果这是您的事情.

除了上面描述的验证和日志记录之外,这些只是一些选项.FWIW,JSR 303,一个bean验证规范,在Hibernate Validator中有一个AOP风格的实现,所以你不需要专门为你的数据对象实现它.Spring框架还内置了验证功能,并且与AspectJ实现了很好的集成,可用于此处描述的一些内容.


Boz*_*zho 11

事实上,AOP使大多数动态代理受益.那是因为您可以在事先不知道的对象周围创建动态代理.

动态代理的另一个有用的方面是当您想要对所有方法应用相同的操作时.使用静态代理,您需要大量重复的代码(在每个代理方法上,您需要对方法进行相同的调用,然后委托给代理对象),动态代理将最小化这一点.

另请注意,Adapter和Decorator是单独的模式.它们在实现方式上看起来像代理模式(通过对象组合),但它们有不同的用途:

  • 装饰器模式允许您拥有多个具体装饰器,从而在运行时添加功能
  • 适配器模式旨在使对象适应不匹配的接口.我能想到的最好的例子是EnumetationIterator-它适应了EnumerationIterator接口.