本文总结 Spring 用到的一些设计模式。
工厂模式
Spring 可以通过 BeanFactory 或 ApplicationContext 创建 bean 对象,ApplicationContext 继承自 BeanFactory。
- BeanFactory:延迟注入,所以占用更少的内存,程序启动速度更快。
- ApplicationContext:容器启动的时候,不管你用没用到,一次性创建所有 bean 。并且 ApplicationContext 继承自 BeanFactory,扩展了功能。
ApplicationContext 有但不限于以下实现类:
- ClassPathXmlApplicationContext:从 ClassPath 中加载 XML 配置文件,创建 ApplicationContext。
- FileSystemXmlApplicationContext:从文件系统中加载 XML 配置文件,创建 ApplicationContext。
- XmlWebApplicationContext:从 Web 系统中加载 XML 配置文件,创建 ApplicationContext。
- AnnotationConfigApplicationContext:通过注解配置类,创建 ApplicationContext。
单例模式
bean 的作用域默认就是单例模式的,Spring 通过 ConcurrentHashMap 作为单例注册表来实现单例模式,key 为 bean name,value 为单例对象。
1 | // 通过 ConcurrentHashMap(线程安全) 实现单例注册表 |
代理模式
Spring AOP 就是基于动态代理的,Spring AOP 根据被代理对象是否有实现接口,分别使用 JDK Proxy 和 CGLIB 实现动态代理。
模板方法
TransactionTemplate.execute 使用到了模板方法,实现事务。Spring 使用 Callback 模式与模板方法模式配合,既达到了代码复用的效果,同时增加了灵活性。
以 Template 结尾的对数据库操作的类,都使用到了模板方法。
1 |
|
观察者模式
观察者模式是一种对象行为型模式。它表示的是一种对象与对象之间具有依赖关系,当一个对象发生改变的时候,依赖这个对象的所有对象也会做出反应。Spring 事件驱动模型就是观察者模式很经典的一个应用。Spring 事件驱动模型非常有用,在很多场景都可以解耦代码。比如我们每次添加商品的时候都需要重新更新商品索引,这个时候就可以利用观察者模式来解决这个问题。
Spring 事件驱动模型
Spring 事件驱动模型有三种角色:
- 事件:ApplicationEvent 是一个抽象类,继承自 java.util.EventObject 并实现了 java.io.Serializable 接口。
- 事件监听者:ApplicationListener 是一个接口,定义了 onApplicationEvent 方法来处理事件。只要实现了 ApplicationListener 接口,就可以完成对事件的监听。
- 事件发布者:ApplicationEventPublisher 作为事件的发布者,也是一个接口。这个接口在 AbstractApplicationContext 中实现。
流程
Spring 中完成对事件的订阅和发布,流程如下:
- 定义一个事件,继承自 ApplicationEvent。
- 定义一个事件监听者,实现 ApplicationListener 接口,重写 onApplicationEvent 方法。
- 使用事件发布者发布消息,通过 ApplicationEventPublisher 的 publishEvent 方法发布消息。
1 | // 定义一个事件,继承自ApplicationEvent并且写相应的构造函数 |
适配器模式
适配器模式将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作。
Spring AOP 通知
Spring AOP:通知用到了适配器模式,与之相关的接口是 AdvisorAdapter
。
Advice 常用的类型有:BeforeAdvice
(目标方法调用前,前置通知)、AfterAdvice
(目标方法调用后,后置通知)、AfterReturningAdvice
(目标方法执行结束后,return 之前)等等。每个类型 Advice(通知)都有对应的拦截器:MethodBeforeAdviceInterceptor
、AfterReturningAdviceInterceptor
、ThrowsAdviceInterceptor
等等。
Spring 预定义的通知要通过对应的适配器,适配成 MethodInterceptor
接口(方法拦截器)类型的对象(如:MethodBeforeAdviceAdapter
通过调用 getInterceptor
方法,将 MethodBeforeAdvice
适配成 MethodBeforeAdviceInterceptor
)。
Spring MVC
Spring MVC:SpringMVC 中有 HandlerAdapter,用于适配执行 Handler。
为什么 SpringMVC 需要适配器?
Spring MVC 中的 Controller
种类众多,不同类型的 Controller
通过不同的方法来对请求进行处理。如果不利用适配器模式的话,DispatcherServlet
直接获取对应类型的 Controller
,需要的自行来判断,像下面这段代码。新增的 Controller
类型就违反了设计模式中的开闭原则。
1 | if(mappedHandler.getHandler() instanceof MultiActionController){ |
装饰器模式
装饰者模式可以动态地给对象添加一些额外的属性或行为。相比于使用继承,装饰者模式更加灵活。Spring 中配置 DataSource 的时候,DataSource 可能是不同的数据库和数据源,可以通过装饰器模式动态的切换不同的数据源。
Spring 中用到的装饰器在类名上含有 Wrapper 或者 Decorator。