11.6 动态代理

Java 的反射 API 还有最后一个功能没讲——创建动态代理。动态代理是实现了一些接口的类(扩展 java.lang.reflect.Proxy 类)。这些类在运行时动态创建,而且会把所有调用都转交给 InvocationHandler 对象处理:

  1. InvocationHandler h = new InvocationHandler() {
  2. @Override
  3. public Object invoke(Object proxy, Method method, Object[] args)
  4. throws Throwable {
  5. String name = method.getName();
  6. System.out.println("Called as: "+ name);
  7. switch (name) {
  8. case "isOpen":
  9. return false;
  10. case "close":
  11. return null;
  12. }
  13. return null;
  14. }
  15. };
  16. Channel c =
  17. (Channel) Proxy.newProxyInstance(Channel.class.getClassLoader(),
  18. new Class[] { Channel.class }, h);
  19. c.isOpen();
  20. c.close();

代理可以用作测试的替身对象(尤其是测试使用模拟方式实现的对象)。

代理的另一个作用是提供接口的部分实现,或者修饰或控制委托对象的某些方面:

  1. public class RememberingList implements InvocationHandler {
  2. private final List<String> proxied = new ArrayList<>();
  3. @Override
  4. public Object invoke(Object proxy, Method method, Object[] args)
  5. throws Throwable {
  6. String name = method.getName();
  7. switch (name) {
  8. case "clear":
  9. return null;
  10. case "remove":
  11. case "removeAll":
  12. return false;
  13. }
  14. return method.invoke(proxied, args);
  15. }
  16. }
  17. RememberingList hList = new RememberingList();
  18. List<String> l =
  19. (List<String>) Proxy.newProxyInstance(List.class.getClassLoader(),
  20. new Class[] { List.class },
  21. hList);
  22. l.add("cat");
  23. l.add("bunny");
  24. l.clear();
  25. System.out.println(l);

代理的功能特别强大而且灵活,很多 Java 框架都有使用。