zoukankan      html  css  js  c++  java
  • SpringMvc学习心得(五)控制器产生与构建

     

    SpringMvc学习心得(五)控制器产生与构建

    标签: springspring mvc框架
     分类:

        在springmvc中,控制器(controller)是一个很重要的概念。在实际项目中,我们一般在控制器里完成具体的业务逻辑。控制器是非常重要,因此讨论控制器的产生和构建就变得很有意义(PS:我们在这里主要讨论基于注解的配置方式)。

      在讨论控制器的相关问题之前,需要考虑的第一个问题是:ApplicationContext的类型是如何确定的?ApplicationContext是spring的IOC机制实现的一个核心,spring的很多功能都是通过ApplicationContext对外输出的。而springmvc的ApplicationContext则是“写死”在FrameworkServlet这个类的field中。

      FrameworkServlet.Java

    [java] view plain copy
     
    1. public abstract class FrameworkServlet extends HttpServletBean {  
    2.   
    3.     /** 
    4.      * Suffix for WebApplicationContext namespaces. If a servlet of this class is 
    5.      * given the name "test" in a context, the namespace used by the servlet will 
    6.      * resolve to "test-servlet". 
    7.      */  
    8.     public static final String DEFAULT_NAMESPACE_SUFFIX = "-servlet";  
    9.   
    10.     /** 
    11.      * Default context class for FrameworkServlet. 
    12.      * @see org.springframework.web.context.support.XmlWebApplicationContext 
    13.      */  
    14.     public static final Class<?> DEFAULT_CONTEXT_CLASS = XmlWebApplicationContext.class;  
    [java] view plain copy
     
    1. //some other code  
      而在XmlWebApplicationContext中,spring“手动”创建了一个ApplicationContextAwareProcessor,并将它注册到beanfactory的beanPostProcessor列表中,具体代码如下:
    [java] view plain copy
     
    1. beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));  

    [java] view plain copy
     
    1. public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {  
    2.         Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");  
    3.         this.beanPostProcessors.remove(beanPostProcessor);  
    4.         this.beanPostProcessors.add(beanPostProcessor);  
    5.         if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {  
    6.             this.hasInstantiationAwareBeanPostProcessors = true;  
    7.         }  
    8.         if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {  
    9.             this.hasDestructionAwareBeanPostProcessors = true;  
    10.         }  
    11.     }  
      至此,产生和构建控制器的前置步骤就完成了。

       控制器的产生:打开@Controller这一注解的源代码,你会发现该注解会被@Component这一注解所修饰。因此,所有被@Controller所修饰的类都会默认被@Component所修饰。同时这也意味着搭配<context:component-scan base-package="xxx.xxxx.xxxx" />这一标签,所有被@Controller所修饰的类都会被注册成为JavaBean。这个JavaBean与其它自定义的JavaBean没有什么区别。而重要的区别则在于被@Controller所修饰的类,能够被之前注册的BeanPostProcessor所扫描并进行处理。

       控制器的构建:springmvc将构建控制器的这一工作交给了BeanPostProcessor进行处理。在<mvc:annotation-driven/>这一标签里,springmvc创建了一个JavaBean,这个bean是RequestMappingHandlerMapping。当这个JavaBean被反射出来但是还没有被初始化的时候,BeanPostProcessor的postProcessBeforeInitialization会发挥作用。当然,由于会首先对JavaBean进行过滤。具体代码如下:

    [java] view plain copy
     
    1. if (bean instanceof ApplicationContextAware) {  
    2.                 ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);  
    3.             }  
      RequestMappingHandlerMapping会使用Applicationcontext的getBeanNamesForType函数去查找所有基类是Object的JavaBean。显而易见,所有的JavaBean都会通过该方法被扫描出来。然后对其中那些被@Controller所修饰的类进行进一步探测和处理。具体代码如下:

     RequestMappingHandlerMapping扫描JavaBean并处理的方法:

    [java] view plain copy
     
    1. protected void initHandlerMethods() {  
    2.         if (logger.isDebugEnabled()) {  
    3.             logger.debug("Looking for request mappings in application context: " + getApplicationContext());  
    4.         }  
    5.           
    6.         String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?  
    7.                 BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :  
    8.                 getApplicationContext().getBeanNamesForType(Object.class));  
    9.   
    10.         for (String beanName : beanNames) {  
    11.             if (isHandler(getApplicationContext().getType(beanName))){  
    12.                 detectHandlerMethods(beanName);  
    13.             }  
    14.         }  
    15.         handlerMethodsInitialized(getHandlerMethods());  
    16.     }  
       isHandler方法(ps:判断是否为控制器):
    [java] view plain copy
     
    1. protected boolean isHandler(Class<?> beanType) {  
    2.         return AnnotationUtils.findAnnotation(beanType, Controller.class) != null;  
    3.     }  

      RequestMappingHandlerMapping中一个很重要的函数是detectHandlerMethods。该函数具体代码如下:

    [java] view plain copy
     
    1. protected void detectHandlerMethods(final Object handler) {  
    2.         Class<?> handlerType = (handler instanceof String) ?   
    3.                 getApplicationContext().getType((String) handler) : handler.getClass();  
    4.   
    5.         final Class<?> userType = ClassUtils.getUserClass(handlerType);  
    6.                   
    7.         Set<Method> methods = HandlerMethodSelector.selectMethods(userType, new MethodFilter() {  
    8.             public boolean matches(Method method) {  
    9.                 return getMappingForMethod(method, userType) != null;  
    10.             }  
    11.         });  
    12.           
    13.         for (Method method : methods) {  
    14.             T mapping = getMappingForMethod(method, userType);  
    15.             registerHandlerMethod(handler, method, mapping);  
    16.         }  
    17.     }  
      可以看到,该函数主要工作是查找handler中的所有method,并根据method生成对应的mapping,并将mapping,method和handler进行注册。而其中最重要的函数则是getMappingForMethod。该函数的主要逻辑是根据method产生一个RequestMappingInfo,然后根据handlerType产生另一个RequestMappingInfo。最后将这两个RequestMappingInfo进行合并。该函数代码如下:
    [java] view plain copy
     
    1. protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {  
    2.         RequestMappingInfo info = null;  
    3.         RequestMapping methodAnnotation = AnnotationUtils.findAnnotation(method, RequestMapping.class);  
    4.         if (methodAnnotation != null) {  
    5.             RequestCondition<?> methodCondition = getCustomMethodCondition(method);  
    6.             info = createRequestMappingInfo(methodAnnotation, methodCondition);  
    7.             RequestMapping typeAnnotation = AnnotationUtils.findAnnotation(handlerType, RequestMapping.class);  
    8.             if (typeAnnotation != null) {  
    9.                 RequestCondition<?> typeCondition = getCustomTypeCondition(handlerType);  
    10.                 info = createRequestMappingInfo(typeAnnotation, typeCondition).combine(info);  
    11.             }  
    12.         }  
    13.         return info;  
    14.     }  
       RequestMappingHandlerMapping通过registerHandlerMethod函数对mapping,handler和method进行注册,RequestMappingHandlerMapping会生成一个LinkedHashMap,并以mapping为key,以handler和method为value。 同时在注册时会检测mapping的是否重复。至此,controller的构建所示完成了。
      既然是以mapping为可以,那么必然会涉及equals函数和hashcode函数,下面是RequestMappingInfode 的equals函数以及hashcode函数。
    [java] view plain copy
     
    1. public int hashCode() {  
    2.         int result = hash;  
    3.         if (result == 0) {  
    4.             result = patternsCondition.hashCode();  
    5.             result = 31 * result + methodsCondition.hashCode();  
    6.             result = 31 * result + paramsCondition.hashCode();  
    7.             result = 31 * result + headersCondition.hashCode();  
    8.             result = 31 * result + consumesCondition.hashCode();  
    9.             result = 31 * result + producesCondition.hashCode();  
    10.             result = 31 * result + customConditionHolder.hashCode();  
    11.             hash = result;  
    12.         }  
    13.         return result;  
    14.     }  
    [java] view plain copy
     
    1. public boolean equals(Object obj) {  
    2.         if (this == obj) {  
    3.             return true;  
    4.         }  
    5.         if (obj != null && obj instanceof RequestMappingInfo) {  
    6.             RequestMappingInfo other = (RequestMappingInfo) obj;  
    7.             return (this.patternsCondition.equals(other.patternsCondition) &&  
    8.                     this.methodsCondition.equals(other.methodsCondition) &&  
    9.                     this.paramsCondition.equals(other.paramsCondition) &&  
    10.                     this.headersCondition.equals(other.headersCondition) &&  
    11.                     this.consumesCondition.equals(other.consumesCondition) &&  
    12.                     this.producesCondition.equals(other.producesCondition) &&   
    13.                     this.customConditionHolder.equals(other.customConditionHolder));  
    14.         }  
    15.         return false;  
    16.     }  
     
    0
  • 相关阅读:
    在取数组的值之前,要判断数组是否为空
    Xcode更改新的Apple ID
    VS2012创建以及调用WebService
    VS添加服务引用和 Web引用的区别
    MongoDB环境搭建
    疑问
    修改导航栏标题的字体和颜色
    self.title,那么self.navigationItem.title和self.tabBarItem.title
    选中cell的时候分割线消失,如何让分割线不消失
    UITableViewCell的分割线顶头
  • 原文地址:https://www.cnblogs.com/developer-ios/p/5919016.html
Copyright © 2011-2022 走看看