SetProxyFactory 类包含一个静态工厂方法 getSetProxy(),它返回一个实现了 Set 的动态代理。代理对象实际实现 Set —— 调用者无法区分(除非通过反射)返回的对象是动态代理。SetProxyFactory 返回的代理只做一件事,把方法分派给传递给工厂方法的 Set 实例。虽然反射代码通常比较难读,但是这里的内容很少,跟上控制流程并不难 —— 只要某个方法在 Set 代理上被调用,它被分派给调用句柄,调用句柄只是反射地调用底层包装的对象上的目标方法。当然,什么都不做的代理可能有点傻,是不是呢?

  什么都不做的适配器

  对于像 SetProxyFactory 这样什么都不做的包装器来说,实际有个很好的应用 —— 可以用它安全地把对象引用的范围缩小到特定接口(或接口集)上,方式是,调用者不能提升引用的类型,使得可以更安全地把对象引用传递给不受信任的代码(例如插件或回调)。清单 3 包含一组类定义,实现了典型的回调场景。从中会看到动态代理可以更方便地替代通常用手工(或用 IDE 提供的代码生成向导)实现的 Adapter 模式。

  清单 3. 典型的回调场景


1.public interface ServiceCallback {  
2. public void doCallback();  
3. }  
4.public interface Service {  
5. public void serviceMethod(ServiceCallback callback);  
6. }  
7.public class ServiceConsumer implements ServiceCallback {  
8. private Service service;  
9....  
10. public void someMethod() {  
11. ...  
12. service.serviceMethod(this);  
13. }  
14. }

  ServiceConsumer 类实现了 ServiceCallback(这通常是支持回调的一个方便途径)并把 this 引用传递给 serviceMethod() 作为回调引用。这种方法的问题是没有机制可以阻止 Service 实现把 ServiceCallback 提升为 ServiceConsumer,并调用 ServiceConsumer 不希望 Service 调用的方法。有时对这个风险并不关心 —— 但有时却关心。如果关心,那么可以把回调对象作为内部类,或者编写一个什么都不做的适配器类(请参阅清单 4 中的 ServiceCallbackAdapter)并用 ServiceCallbackAdapter 包装 ServiceConsumer。ServiceCallbackAdapter 防止 Service 把 ServiceCallback 提升为 ServiceConsumer。

  清单 4. 用于安全地把对象限制在一个接口上以便不被恶意代码不能的适配器类

1.public class ServiceCallbackAdapter implements ServiceCallback {  
2. private final ServiceCallback cb;  
3.public ServiceCallbackAdapter(ServiceCallback cb) {  
4. this.cb = cb;  
5. }  
6.public void doCallback() {  
7. cb.doCallback();  
8. }  
9. }