Spring

119 阅读4分钟

前言

本文主要介绍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方法。

2、自动装配原理

2.1、介绍

2.2、原理

2.2.1、@EnableAutoConfiguration:实现自动装配的核心注解

2.2.2、AutoConfigurationImportSelector:加载自动装配类

2.3、如何实现一个 Starter