前言
本文主要介绍Spring中用到的设计模式和它的自动装配,掌握了这些,可以帮你理解Spring的实现原理,提高阅读源码的效率,还可以教你在实际开发中运用这些模式,写出灵活高效、可扩展的代码。
1、设计模式
1.1、策略模式
1、对接口方法参数的处理
比如说,我们经常在写接口的时候,会使用到了@PathVariable、@RequestParam、@RequestBody等注解,一旦我们使用了注解,SpringMVC会处理注解,从请求中获取到参数,然后再调用接口传递过来,而这个过程,就使用到了策略模式。
对于这类参数的解析,SpringMVC提供了一个策略接口HandlerMethodArgumentResolver
HandlerMethodArgumentResolver
这个接口的定义就跟我们上面定义的差不多,不同的参数处理只需要实现这个解决就行,比如上面提到的几个注解,都有对应的实现。
比如处理@RequestParam注解的RequestParamMethodArgumentResolver的实现。
RequestParamMethodArgumentResolver
当然还有其它很多的实现,如果想知道各种注解处理的过程,只需要找到对应的实现类就行了。
2、对接口返回值的处理
同样,SpringMVC对于返回值的处理也是基于策略模式来实现的。
HandlerMethodReturnValueHandler
HandlerMethodReturnValueHandler接口定义跟上面都是同一种套路。
比如说,常见的对于@ResponseBody注解处理的实现RequestResponseBodyMethodProcessor。
ResponseBody注解处理的实现RequestResponseBodyMethodProcessor
同样,HandlerMethodReturnValueHandler的实现也有很多,这里就不再举例了。
策略模式在Spring的运用远不止这两处,对于配置文件的加载PropertySourceLoader也是策略模式的运用。
1.2、工厂设计模式
我们知道Spring中的Bean是通过BeanFactory创建的。
BeanFactory就是Bean生成的工厂。一个Spring Bean在生成过程中会经历复杂的一个生命周期,而这些生命周期对于使用者来说是无需关心的,所以就可以将Bean创建过程的逻辑给封装起来,提取出一个Bean的工厂。
1.3、单例设计模式
静态常量方式属于饿汉式,以静态变量的方式声明对象。这种单例模式在Spring中使用的比较多,举个例子,在Spring中对于Bean的名称生成有个类AnnotationBeanNameGenerator就是单例的。
AnnotationBeanNameGenerator
1.4、代理设计模式
Spring AOP其实跟静态代理很像,最终其实也是调用目标对象的方法,只不过是动态生成的,这里就不展开讲解了。
1.5、模板方法
我们都知道,在Spring中,ApplicationContext在使用之前需要调用一下refresh方法,而refresh方法就定义了整个容器刷新的执行流程代码。
refresh方法部分截图
在整个刷新过程有一个onRefresh方法
onRefresh方法
而onRefresh方法默认是没有做任何事,并且在注释上有清楚两个单词Template method,翻译过来就是模板方法的意思,所以onRefresh就是一个模板方法,并且方法内部的注释也表明了,这个方法是为了子类提供的。
在Web环境下,子类会重写这个方法,然后创建一个Web服务器。
1.6、观察者模式
Spring事件,就是Spring基于观察者模式实现的一套API。
Spring事件的实现比较简单,其实就是当Bean在生成完成之后,会将所有的ApplicationListener接口实现(监听器)添加到ApplicationEventMulticaster中。
ApplicationEventMulticaster可以理解为一个调度中心的作用,可以将事件通知给监听器,触发监听器的执行。
ApplicationEventMulticaster可以理解为一个总线
retrieverCache中存储了事件类型和对应监听器的缓存。当发布事件的时候,会通过事件的类型找到对应的监听器,然后循环调用监听器。
所以,Spring的观察者模式实现的其实也不复杂。
1.7、责任链模式
在SpringMVC中,可以通过使用HandlerInterceptor对每个请求进行拦截。
HandlerInterceptor
而HandlerInterceptor其实就使用到了责任链模式,但是这种责任链模式的写法跟上面举的例子写法不太一样。
对于HandlerInterceptor的调用是在HandlerExecutionChain中完成的。
HandlerExecutionChain
比如说,对于请求处理前的拦截,就在是这样调用的。
其实就是循环遍历每个HandlerInterceptor,调用preHandle方法。