我需要一些建议,了解哪些情况下动态代理比普通代理更有用。
我已经花了很多精力学习如何有效地使用动态代理。在这个问题中,暂时不考虑像AspectJ这样的框架可以执行基本上我们尝试使用动态代理实现的所有功能,或者例如CGLIB可以用于解决动态代理的某些缺点。
使用案例
- 装饰器-例如,在方法调用时执行日志记录,或缓存复杂操作的返回值
- 维护契约 - 即,确保参数在接受范围内并且返回类型符合接受的值。
- 适配器 - 看到某篇聪明的文章描述了这个有用的设计模式。不过我很少遇到这种情况。
还有其他用例吗?
动态代理优势
- 装饰器:记录所有方法调用,例如:
public Object invoke(Object target, Method method, Object[] arguments) {
System.out.println("before method " + method.getName());
return method.invoke(obj, args);
}
}
装饰者模式确实很有用,因为它允许在所有代理方法中产生副作用(尽管这种行为是使用方面的经典示例..)。
- 契约:与常规代理相比,我们不需要实现完整的接口。例如,
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;
}
}
另一方面,合同只是为了避免实现完整接口而获得好处。然而,重构代理方法将会默默地使动态代理失效。
结论
因此,我在这里看到一个真正的用例和一个可疑的用例。你的意见是什么?