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

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

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

  FrameworkServlet.java

public abstract class FrameworkServlet extends HttpServletBean {

	/**
	 * Suffix for WebApplicationContext namespaces. If a servlet of this class is
	 * given the name "test" in a context, the namespace used by the servlet will
	 * resolve to "test-servlet".
	 */
	public static final String DEFAULT_NAMESPACE_SUFFIX = "-servlet";

	/**
	 * Default context class for FrameworkServlet.
	 * @see org.springframework.web.context.support.XmlWebApplicationContext
	 */
	public static final Class<?> DEFAULT_CONTEXT_CLASS = XmlWebApplicationContext.class;
        //some other code
  而在XmlWebApplicationContext中,spring“手动”创建了一个ApplicationContextAwareProcessor,并将它注册到beanfactory的beanPostProcessor列表中,具体代码如下:

beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
		Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
		this.beanPostProcessors.remove(beanPostProcessor);
		this.beanPostProcessors.add(beanPostProcessor);
		if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
			this.hasInstantiationAwareBeanPostProcessors = true;
		}
		if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
			this.hasDestructionAwareBeanPostProcessors = true;
		}
	}
  至此,产生和构建控制器的前置步骤就完成了。

   控制器的产生:打开@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进行过滤。具体代码如下:

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

 RequestMappingHandlerMapping扫描JavaBean并处理的方法:

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 (isHandler(getApplicationContext().getType(beanName))){
				detectHandlerMethods(beanName);
			}
		}
		handlerMethodsInitialized(getHandlerMethods());
	}
   isHandler方法(ps:判断是否为控制器):

protected boolean isHandler(Class<?> beanType) {
		return AnnotationUtils.findAnnotation(beanType, Controller.class) != null;
	}

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

protected void detectHandlerMethods(final Object handler) {
		Class<?> handlerType = (handler instanceof String) ? 
				getApplicationContext().getType((String) handler) : handler.getClass();

		final Class<?> userType = ClassUtils.getUserClass(handlerType);
				
		Set<Method> methods = HandlerMethodSelector.selectMethods(userType, new MethodFilter() {
			public boolean matches(Method method) {
				return getMappingForMethod(method, userType) != null;
			}
		});
		
		for (Method method : methods) {
			T mapping = getMappingForMethod(method, userType);
			registerHandlerMethod(handler, method, mapping);
		}
	}
  可以看到,该函数主要工作是查找handler中的所有method,并根据method生成对应的mapping,并将mapping,method和handler进行注册。而其中最重要的函数则是getMappingForMethod。该函数的主要逻辑是根据method产生一个RequestMappingInfo,然后根据handlerType产生另一个RequestMappingInfo。最后将这两个RequestMappingInfo进行合并。该函数代码如下:

protected 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;
	}
    RequestMappingHandlerMapping通过registerHandlerMethod函数对mapping,handler和method进行注册,RequestMappingHandlerMapping会生成一个LinkedHashMap,并以mapping为key,以handler和method为value。 同时在注册时会检测mapping的是否重复。至此,controller的构建所示完成了。
  既然是以mapping为可以,那么必然会涉及equals函数和hashcode函数,下面是RequestMappingInfode 的equals函数以及hashcode函数。


public int hashCode() {
		int result = hash;
		if (result == 0) {
			result = patternsCondition.hashCode();
			result = 31 * result + methodsCondition.hashCode();
			result = 31 * result + paramsCondition.hashCode();
			result = 31 * result + headersCondition.hashCode();
			result = 31 * result + consumesCondition.hashCode();
			result = 31 * result + producesCondition.hashCode();
			result = 31 * result + customConditionHolder.hashCode();
			hash = result;
		}
		return result;
	}


public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj != null && obj instanceof RequestMappingInfo) {
			RequestMappingInfo other = (RequestMappingInfo) obj;
			return (this.patternsCondition.equals(other.patternsCondition) &&
					this.methodsCondition.equals(other.methodsCondition) &&
					this.paramsCondition.equals(other.paramsCondition) &&
					this.headersCondition.equals(other.headersCondition) &&
					this.consumesCondition.equals(other.consumesCondition) &&
					this.producesCondition.equals(other.producesCondition) && 
					this.customConditionHolder.equals(other.customConditionHolder));
		}
		return false;
	}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值