被 RequestMapping 注解封印的方法模型类。
封装了关于处理器方法信息的方法和bean类 。 提供了对方法参数,方法返回值,方法注释等方便地访问入口。
该类可以使用bean实例或具有bean名称(例如lazy-init bean,prototype bean)来创建。 使用createWithResolvedBean()获得HandlerMethod实例,被BeanFactory解析过的。
1 字段
// Object类型,可以是Bean,也可以是个String 的 BeanName private final Object bean; // 如果是BeanName,就靠它拿到Bean实例 @Nullable private final BeanFactory beanFactory; private final Class<?> beanType; // 该方法所属的类 private final Method method; // 该方法本身 private final Method bridgedMethod; // 被桥接的方法,如果method是原生的,它的值同method // 方法参数的类实例 一个MethodParameter就是一个入参 private final MethodParameter[] parameters; @Nullable private HttpStatus responseStatus; // http状态码(负责处理和返回) @Nullable private String responseStatusReason; // 状态码原因 // 通过createWithResolvedBean()解析此handlerMethod实例的handlerMethod。 @Nullable private HandlerMethod resolvedFromHandlerMethod; // 接口入参上的注解 @Nullable private volatile List<Annotation[][]> interfaceParameterAnnotations;
构造器
// 它的构造方法众多 此处我只写出关键的步骤 public HandlerMethod(Object bean, Method method) { ... this.beanType = ClassUtils.getUserClass(bean); this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); this.parameters = initMethodParameters(); ... evaluateResponseStatus(); } // 这个构造方法抛出了一个异常NoSuchMethodException public HandlerMethod(Object bean, String methodName, Class<?>... parameterTypes) throws NoSuchMethodException { ... this.method = bean.getClass().getMethod(methodName, parameterTypes); this.parameters = initMethodParameters(); ... evaluateResponseStatus(); } // 此处传的是BeanName public HandlerMethod(String beanName, BeanFactory beanFactory, Method method) { ... // 这部判断:这个BeanName是必须存在的 Class<?> beanType = beanFactory.getType(beanName); if (beanType == null) { throw new IllegalStateException("Cannot resolve bean type for bean with name '" + beanName + "'"); } this.parameters = initMethodParameters(); ... evaluateResponseStatus(); } // 供给子类copy使用的 protected HandlerMethod(HandlerMethod handlerMethod) { ... } // 所有构造都执行了两个方法:initMethodParameters和evaluateResponseStatus
API
createWithResolvedBean
如果所提供的实例包含一个bean的名称,而不是一个对象实例。
则从 bean 工厂解析该名称得到 bean 类(@Component 注解的类),再创建HandlerMethod并返回
// 初始化该方法所有的入参,此处使用的是内部类HandlerMethodParameter // 注意:处理了泛型的~~~ private MethodParameter[] initMethodParameters() { int count = this.bridgedMethod.getParameterCount(); MethodParameter[] result = new MethodParameter[count]; for (int i = 0; i < count; i++) { HandlerMethodParameter parameter = new HandlerMethodParameter(i); GenericTypeResolver.resolveParameterType(parameter, this.beanType); result[i] = parameter; } return result; } // 看看方法上是否有标注了@ResponseStatus注解(接口上或者父类 组合注解上都行) // 若方法上没有,还会去所在的类上去看看有没有标注此注解 // 主要只解析这个注解,把它的两个属性code和reason拿过来,最后就是返回它俩了~~~ // code状态码默认是HttpStatus.INTERNAL_SERVER_ERROR-->(500, "Internal Server Error") private void evaluateResponseStatus() { ResponseStatus annotation = getMethodAnnotation(ResponseStatus.class); if (annotation == null) { annotation = AnnotatedElementUtils.findMergedAnnotation(getBeanType(), ResponseStatus.class); } if (annotation != null) { this.responseStatus = annotation.code(); this.responseStatusReason = annotation.reason(); } } ... // 省略所有属性的get方法(无set方法) // 返回方法返回值的类型 此处也使用的MethodParameter public MethodParameter getReturnType() { return new HandlerMethodParameter(-1); } // 注意和上面的区别。举个列子:比如方法返回的是Object,但实际return “fsx”字符串 // 那么上面返回永远是Object.class,下面你实际的值是什么类型就是什么类型 public MethodParameter getReturnValueType(@Nullable Object returnValue) { return new ReturnValueMethodParameter(returnValue); } // 该方法的返回值是否是void public boolean isVoid() { return Void.TYPE.equals(getReturnType().getParameterType()); } // 返回标注在方法上的指定类型的注解 父方法也成 // 子类ServletInvocableHandlerMethod对下面两个方法都有复写~~~ @Nullable public <A extends Annotation> A getMethodAnnotation(Class<A> annotationType) { return AnnotatedElementUtils.findMergedAnnotation(this.method, annotationType); } public <A extends Annotation> boolean hasMethodAnnotation(Class<A> annotationType) { return AnnotatedElementUtils.hasAnnotation(this.method, annotationType); } // resolvedFromHandlerMethod虽然它只能被构造进来,但是它实际是铜鼓调用下面方法赋值 @Nullable public HandlerMethod getResolvedFromHandlerMethod() { return this.resolvedFromHandlerMethod; } public String getShortLogMessage() { return getBeanType().getName() + "#" + this.method.getName() + "[" + this.method.getParameterCount() + " args]"; } // 这个方法是提供给内部类HandlerMethodParameter来使用的~~ 它使用的数据结构还是蛮复杂的 private List<Annotation[][]> getInterfaceParameterAnnotations() { List<Annotation[][]> parameterAnnotations = this.interfaceParameterAnnotations; if (parameterAnnotations == null) { parameterAnnotations = new ArrayList<>(); // 遍历该方法所在的类所有的实现的接口们(可以实现N个接口嘛) for (Class<?> ifc : this.method.getDeclaringClass().getInterfaces()) { // getMethods:拿到所有的public的方法,包括父接口的 接口里的私有方法可不会获取来 for (Method candidate : ifc.getMethods()) { // 判断这个接口方法是否正好是当前method复写的这个~~~ // 刚好是复写的方法,那就添加进来,标记为接口上的注解们~~~ if (isOverrideFor(candidate)) { // getParameterAnnotations返回的是个二维数组~~~~ // 因为参数有多个,且每个参数前可以有多个注解 parameterAnnotations.add(candidate.getParameterAnnotations()); } } } this.interfaceParameterAnnotations = parameterAnnotations; } return parameterAnnotations; } // 看看内部类的关键步骤 protected class HandlerMethodParameter extends SynthesizingMethodParameter { @Nullable private volatile Annotation[] combinedAnnotations; ... // 父类只会在本方法拿,这里支持到了接口级别 @Override public Annotation[] getParameterAnnotations() { Annotation[] anns = this.combinedAnnotations; if (anns == null) { // 都只需要解析一次 anns = super.getParameterAnnotations(); int index = getParameterIndex(); if (index >= 0) { // 有入参分析 for (Annotation[][] ifcAnns : getInterfaceParameterAnnotations()) { if (index < ifcAnns.length) { Annotation[] paramAnns = ifcAnns[index]; if (paramAnns.length > 0) { List<Annotation> merged = new ArrayList<>(anns.length + paramAnns.length); merged.addAll(Arrays.asList(anns)); for (Annotation paramAnn : paramAnns) { boolean existingType = false; for (Annotation ann : anns) { if (ann.annotationType() == paramAnn.annotationType()) { existingType = true; break; } } if (!existingType) { merged.add(adaptAnnotation(paramAnn)); } } anns = merged.toArray(new Annotation[0]); } } } } this.combinedAnnotations = anns; } return anns; } } // 返回值的真正类型 private class ReturnValueMethodParameter extends HandlerMethodParameter { @Nullable private final Object returnValue; public ReturnValueMethodParameter(@Nullable Object returnValue) { super(-1); // 此处传的-1哦~~~~ 比0小是很有意义的 this.returnValue = returnValue; } ... // 返回值类型使用returnValue @Override public Class<?> getParameterType() { return (this.returnValue != null ? this.returnValue.getClass() : super.getParameterType()); } } }
继承树
子类都有invoke能力