springMVC (五) annotation-driven

来源:互联网 发布:二胡软件 编辑:程序博客网 时间:2024/06/05 19:49

<annotation-driven/>的解析类

/** * A {@link BeanDefinitionParser} that provides the configuration for the * {@code <annotation-driven/>} MVC namespace element. * * <p>This class registers the following {@link HandlerMapping}s:</p>  //注册的handlerMapping * <ul> * <li>{@link RequestMappingHandlerMapping} * ordered at 0 for mapping requests to annotated controller methods. * <li>{@link BeanNameUrlHandlerMapping} * ordered at 2 to map URL paths to controller bean names. * </ul> * * <p><strong>Note:</strong> Additional HandlerMappings may be registered * as a result of using the {@code <view-controller>} or the * {@code <resources>} MVC namespace elements. * * <p>This class registers the following {@link HandlerAdapter}s:        //注册的handlerAdapter * <ul> * <li>{@link RequestMappingHandlerAdapter} * for processing requests with annotated controller methods. * <li>{@link HttpRequestHandlerAdapter} * for processing requests with {@link HttpRequestHandler}s. * <li>{@link SimpleControllerHandlerAdapter} * for processing requests with interface-based {@link Controller}s. * </ul> * * <p>This class registers the following {@link HandlerExceptionResolver}s: * <ul> * <li>{@link ExceptionHandlerExceptionResolver} for handling exceptions * through @{@link ExceptionHandler} methods. * <li>{@link ResponseStatusExceptionResolver} for exceptions annotated * with @{@link ResponseStatus}. * <li>{@link DefaultHandlerExceptionResolver} for resolving known Spring * exception types * </ul> * * <p>This class registers an {@link org.springframework.util.AntPathMatcher} * and a {@link org.springframework.web.util.UrlPathHelper} to be used by: * <ul> *  <li>the {@link RequestMappingHandlerMapping}, *  <li>the {@link HandlerMapping} for ViewControllers *  <li>and the {@link HandlerMapping} for serving resources * </ul> * Note that those beans can be configured by using the {@code path-matching} MVC namespace element. * * <p>Both the {@link RequestMappingHandlerAdapter} and the * {@link ExceptionHandlerExceptionResolver} are configured with instances of * the following by default: * <ul> * <li>A {@link ContentNegotiationManager} * <li>A {@link DefaultFormattingConversionService} * <li>A {@link org.springframework.validation.beanvalidation.LocalValidatorFactoryBean} * if a JSR-303 implementation is available on the classpath * <li>A range of {@link HttpMessageConverter}s depending on what 3rd party * libraries are available on the classpath. * </ul> * * @author Keith Donald * @author Juergen Hoeller * @author Arjen Poutsma * @author Rossen Stoyanchev * @author Brian Clozel * @author Agim Emruli * @since 3.0 */class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser 

RequestMappingHandlerMapping初始化handlerMethods

RequestMappingHandlerMapping父类的父类AbstractHandlerMethodMapping的initHandlerMethods方法

/** * Scan beans in the ApplicationContext, detect and register handler methods. * @see #isHandler(Class) * @see #getMappingForMethod(Method, Class) * @see #handlerMethodsInitialized(Map) */protected void initHandlerMethods() {if (logger.isDebugEnabled()) {logger.debug("Looking for request mappings in application context: " + getApplicationContext());}String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :getApplicationContext().getBeanNamesForType(Object.class));for (String beanName : beanNames) {if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX) &&isHandler(getApplicationContext().getType(beanName))){detectHandlerMethods(beanName);}}handlerMethodsInitialized(getHandlerMethods());}
其中isHandler(getApplicationContext().getType(beanName))的实现

/** * {@inheritDoc} * Expects a handler to have a type-level @{@link Controller} annotation. */@Overrideprotected boolean isHandler(Class<?> beanType) {return ((AnnotationUtils.findAnnotation(beanType, Controller.class) != null) ||(AnnotationUtils.findAnnotation(beanType, RequestMapping.class) != null));}

即只要含有@Controller或者@RequestMapping就返回true,进行下一步处理detectHandlerMethods()

/** * Look for handler methods in a handler. * @param handler the bean name of a handler or a handler instance */protected void detectHandlerMethods(final Object handler) {Class<?> handlerType =(handler instanceof String ? getApplicationContext().getType((String) handler) : handler.getClass());// Avoid repeated calls to getMappingForMethod which would rebuild RequestMappingInfo instancesfinal Map<Method, T> mappings = new IdentityHashMap<Method, T>();final Class<?> userType = ClassUtils.getUserClass(handlerType);Set<Method> methods = HandlerMethodSelector.selectMethods(userType, new MethodFilter() {@Overridepublic boolean matches(Method method) {T mapping = getMappingForMethod(method, userType);if (mapping != null) {mappings.put(method, mapping);return true;}else {return false;}}});for (Method method : methods) {registerHandlerMethod(handler, method, mappings.get(method));}}

过滤条件方法

/** * Uses method and type-level @{@link RequestMapping} annotations to create * the RequestMappingInfo. * @return the created RequestMappingInfo, or {@code null} if the method * does not have a {@code @RequestMapping} annotation. * @see #getCustomMethodCondition(Method) * @see #getCustomTypeCondition(Class) */@Overrideprotected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {RequestMappingInfo info = null;RequestMapping methodAnnotation = AnnotationUtils.findAnnotation(method, RequestMapping.class);if (methodAnnotation != null) {RequestCondition<?> methodCondition = getCustomMethodCondition(method);info = createRequestMappingInfo(methodAnnotation, methodCondition);RequestMapping typeAnnotation = AnnotationUtils.findAnnotation(handlerType, RequestMapping.class);if (typeAnnotation != null) {RequestCondition<?> typeCondition = getCustomTypeCondition(handlerType);info = createRequestMappingInfo(typeAnnotation, typeCondition).combine(info);}}return info;}

如果找到@RequestMapping注解的方法,则由这个注解内容生成一个RequestMappingInfo返回


/**     * Register a handler method and its unique mapping.     * @param handler the bean name of the handler or the handler instance     * @param method the method to register     * @param mapping the mapping conditions associated with the handler method     * @throws IllegalStateException if another method was already registered     * under the same mapping     */    protected void registerHandlerMethod(Object handler, Method method, T mapping) {        HandlerMethod newHandlerMethod = createHandlerMethod(handler, method);        HandlerMethod oldHandlerMethod = this.handlerMethods.get(mapping);        if (oldHandlerMethod != null && !oldHandlerMethod.equals(newHandlerMethod)) {            throw new IllegalStateException("Ambiguous mapping found. Cannot map '" + newHandlerMethod.getBean() +                    "' bean method \n" + newHandlerMethod + "\nto " + mapping + ": There is already '" +                    oldHandlerMethod.getBean() + "' bean method\n" + oldHandlerMethod + " mapped.");        }        this.handlerMethods.put(mapping, newHandlerMethod);//key为RequestMappingInfo  value为handler和method创建的handlerMethod类        if (logger.isInfoEnabled()) {            logger.info("Mapped \"" + mapping + "\" onto " + newHandlerMethod);        }        Set<String> patterns = getMappingPathPatterns(mapping);        for (String pattern : patterns) {            if (!getPathMatcher().isPattern(pattern)) {                this.urlMap.add(pattern, mapping);//key为the URL path patterns   value为RequestMappingInfo              }        }        if (this.namingStrategy != null) {            String name = this.namingStrategy.getName(newHandlerMethod, mapping);            updateNameMap(name, newHandlerMethod);        }    }





0 0