3. 源码分析

本章将分析 AbstractDirectory 和它两个子类的源码。AbstractDirectory 封装了 Invoker 列举流程,具体的列举逻辑则由子类实现,这是典型的模板模式。所以,接下来我们先来看一下 AbstractDirectory 的源码。

  1. public List<Invoker<T>> list(Invocation invocation) throws RpcException {
  2. if (destroyed) {
  3. throw new RpcException("Directory already destroyed...");
  4. }
  5. // 调用 doList 方法列举 Invoker,doList 是模板方法,由子类实现
  6. List<Invoker<T>> invokers = doList(invocation);
  7. // 获取路由 Router 列表
  8. List<Router> localRouters = this.routers;
  9. if (localRouters != null && !localRouters.isEmpty()) {
  10. for (Router router : localRouters) {
  11. try {
  12. // 获取 runtime 参数,并根据参数决定是否进行路由
  13. if (router.getUrl() == null || router.getUrl().getParameter(Constants.RUNTIME_KEY, false)) {
  14. // 进行服务路由
  15. invokers = router.route(invokers, getConsumerUrl(), invocation);
  16. }
  17. } catch (Throwable t) {
  18. logger.error("Failed to execute router: ...");
  19. }
  20. }
  21. }
  22. return invokers;
  23. }
  24. // 模板方法,由子类实现
  25. protected abstract List<Invoker<T>> doList(Invocation invocation) throws RpcException;

上面就是 AbstractDirectory 的 list 方法源码,这个方法封装了 Invoker 的列举过程。如下:

  1. 调用 doList 获取 Invoker 列表
  2. 根据 Router 的 getUrl 返回值为空与否,以及 runtime 参数决定是否进行服务路由

以上步骤中,doList 是模板方法,需由子类实现。Router 的 runtime 参数这里简单说明一下,这个参数决定了是否在每次调用服务时都执行路由规则。如果 runtime 为 true,那么每次调用服务前,都需要进行服务路由。这个对性能造成影响,配置时需要注意。

关于 AbstractDirectory 就分析这么多,下面开始分析子类的源码。