/**
  * 返回该Controller的所有访问控制注解
  *
  * @return
  */
 private List<Annotation> getAuthzAnnotations(Class<? extends Controller> targetClass) {
   List<Annotation> annotations = new ArrayList<Annotation>();
   for (Class<? extends Annotation> annClass : AUTHZ_ANNOTATION_CLASSES) {
     Annotation a = targetClass.getAnnotation(annClass);
     if (a != null) {
       annotations.add(a);
     }
   }
   return annotations;
 }
  /** 启动插件 */
  @Override
  public boolean start() {
    Set<String> excludedMethodName = buildExcludedMethodName();
    ConcurrentMap<String, AuthzHandler> authzMaps = new ConcurrentHashMap<String, AuthzHandler>();
    // 逐个访问所有注册的Controller,解析Controller及action上的所有Shiro注解。
    // 并依据这些注解,actionKey提前构建好权限检查处理器。
    for (Entry<String, Class<? extends Controller>> entry : routes.getEntrySet()) {
      Class<? extends Controller> controllerClass = entry.getValue();

      String controllerKey = entry.getKey();

      // 获取Controller的所有Shiro注解。
      List<Annotation> controllerAnnotations = getAuthzAnnotations(controllerClass);
      // 逐个遍历方法。
      Method[] methods = controllerClass.getMethods();
      for (Method method : methods) {
        // 排除掉Controller基类的所有方法,并且只关注没有参数的Action方法。
        if (!excludedMethodName.contains(method.getName())
            && method.getParameterTypes().length == 0) {
          // 若该方法上存在ClearShiro注解,则对该action不进行访问控制检查。
          if (isClearShiroAnnotationPresent(method)) {
            continue;
          }
          // 获取方法的所有Shiro注解。
          List<Annotation> methodAnnotations = getAuthzAnnotations(method);
          // 依据Controller的注解和方法的注解来生成访问控制处理器。
          AuthzHandler authzHandler = createAuthzHandler(controllerAnnotations, methodAnnotations);
          // 生成访问控制处理器成功。
          if (authzHandler != null) {
            // 构建ActionKey,参考ActionMapping中实现
            String actionKey = createActionKey(controllerClass, method, controllerKey);
            // 添加映射
            authzMaps.put(actionKey, authzHandler);
          }
        }
      }
    }
    // 注入到ShiroKit类中。ShiroKit类以单例模式运行。
    ShiroKit.init(jdbcAuthzService, authzMaps, isAnd);
    return true;
  }
  /**
   * 构建actionkey,参考ActionMapping中的实现。
   *
   * @param controllerClass
   * @param method
   * @param controllerKey
   * @return
   */
  private String createActionKey(
      Class<? extends Controller> controllerClass, Method method, String controllerKey) {
    String methodName = method.getName();
    String actionKey = "";

    ActionKey ak = method.getAnnotation(ActionKey.class);
    if (ak != null) {
      actionKey = ak.value().trim();
      if ("".equals(actionKey))
        throw new IllegalArgumentException(
            controllerClass.getName()
                + "."
                + methodName
                + "(): The argument of ActionKey can not be blank.");
      if (!actionKey.startsWith(SLASH)) actionKey = SLASH + actionKey;
    } else if (methodName.equals("index")) {
      actionKey = controllerKey;
    } else {
      actionKey =
          controllerKey.equals(SLASH) ? SLASH + methodName : controllerKey + SLASH + methodName;
    }
    return actionKey;
  }