spring design patterns
本文最后更新于:2022年9月20日 下午
Spring源码中的设计模式
设计模式的七大原则
设计原则名称 | 定 义 | 使用频率 |
---|---|---|
单一职责原则 (Single Responsibility Principle, SRP) | 一个类只负责一个功能领域中的相应职责 | ★★★★☆ |
开闭原则 (Open-Closed Principle, OCP) | 软件实体应对扩展开放,而对修改关闭 | ★★★★★ |
里氏代换原则 (Liskov Substitution Principle, LSP) | 所有引用基类对象的地方能够透明地使用其子类的对象 | ★★★★★ |
依赖倒转原则 (Dependence Inversion Principle, DIP) | 抽象不应该依赖于细节,细节应该依赖于抽象 | ★★★★★ |
接口隔离原则 (Interface Segregation Principle, ISP) | 使用多个专门的接口,而不使用单一的总接口 | ★★☆☆☆ |
合成复用原则 (Composite Reuse Principle, CRP) | 尽量使用对象组合,而不是继承来达到复用的目的 | ★★★★☆ |
迪米特法则 (Law of Demeter, LoD) | 一个软件实体应当尽可能少地与其他实体发生相互作用 | ★★★☆☆ |
设计模式的分类
Iterator模式
Spring 框架还通过 CompositeIterator 类扩展迭代器模式。该模式主要用于 Java 语言的集合框架中,用于按顺序迭代访问元素
Adapter 模式
org.springframework.web.reactive#HandlerAdapter
实现 Handler 的类有
HttpRequestHandlerAdapter (org.springframework.web.servlet.mvc)
SimpleServletHandlerAdapter (org.springframework.web.servlet.handler)
HandlerFunctionAdapter (org.springframework.web.servlet.function.support)
CompositeHandlerAdapter (org.springframework.boot.actuate.autoconfigure.web.servlet)
AbstractHandlerMethodAdapter (org.springframework.web.servlet.mvc.method)
SimpleControllerHandlerAdapter (org.springframework.web.servlet.mvc)
spring定义了一个适配器接口,使得每一种Controller有一种对应的适配器实现类,让适配器代替controller执行相应的方法。这样在扩展Controller 时,只需要增加一个适配器类就完成了SpringMVC的扩展了
Template Method 模式
org.springframework.context.support#AbstractApplicationContext.refresh()
refresh方法中定义了一套流程,其中postProcessBeanFactory、onRefresh以及一些其他方法中调用的方法,都是延迟到子类中实现,在AbstractApplicationContext类中只是定义了一个空实现,这就是模板方法模式中的钩子方法
Spring 中模版方法具体的实现:
Singleton 模式
org.springframework.beans.factory.support#AbstractBeanFactory.getBean()
Spring的依赖注入(包括lazy-init方式)都是发生在AbstractBeanFactory 的 getBean里。getBean 的 doGetBean方法调用 getSingleton 进行 bean 的创建。lazy-init 方式,在容器初始化时候进行调用,非lazy-init方式,在用户向容器第一次索要bean时进行调用,其中 getSingleton 就是使用双重检索来实现单例 Bean 的创建
Prototype模式
org.springframework.beans.factory.support#AbstractAutowireCapableBeanFactory.doCreateBean()
在创建 Bean 是会校验是否是原型模式,然后通过对象拷贝的方式创建原型对象
org.springframework.beans.factory.support#RootBeanDefinition.RootBeanDefinition
在创建 BeanDefintion 对象时直接通过 RootBeanDefinition 构造方法设置各种属性和值创建对象
Builder模式
org.springframework.web.util#UriComponents
处理 URL 将其处理以后封装为 UriComponents 返回
(扩展:JDK 中 StringBuilder 中 实现了 Append 方法也是 Builder 模式的一种实现)
Abstract Factory 模式
org.springframework.beans.factory#BeanFactory
在 Spring 中,BeanFactory 是用于管理 Bean 的一个工厂,所有工厂都是 BeanFactory 的子类。这样我们可以通过 IOC 容器来管理访问 Bean,根据不同的策略调用 getBean() 方法,从而获得具体对象
BeanFactory 的子类主要有:
ClassPathXmlApplicationContext
XmlWebApplicationContext
StaticWebApplicationContext
StaticApplicationContext
在 Spring 中,DefaultListableBeanFactory 实现了所有工厂的公共逻辑
Bridge 模式
org.springframework.core#BridgeMethodResolver
这个桥接解析器的作用是通过桥接方法,找到桥接方法对应的原始方法。当一个子类在继承(或实现)一个父类(或接口)的泛型方法时,在子类中明确指定了泛型类型,那么在编译时编译器会自动生成桥接方法。BridgeMethodResolve 就是通过判断方法名、参数的个数以及泛型类型参数来获取原始的方法。具体实现:
- 如果不是桥接,就直接返回
- 先从本地缓存独取,缓存中有则直接返回
- 以方法名称和入参格式相等进行筛选
- 递归该类及其父类所有的方法,符合条件就添加进来
- 如果符合条件就直接采用,否则,调用searchCandidates方法再次筛选。
- 如果找不到实际方法,则返回原来的桥连方法。
- 结果放入缓存。
Strategy 模式
org.springframework.beans.factory.support#InstantiationStrategy
创建 bean 实例是有三种策略:
基于无参构造函数创建 bean 实例
基于指定构造函数创建 bean 实例
基于工厂方法创建 bean 实例
org.springframework.beans.factory.support#BeanDefinitionReader
读取 Bean 相关定义的类
Groovy BeanDefinitionReader
PropertiesBeanDefinitionReader
XmlBeanDefinitionReader
ConfigurationClassBeanDefinitionReader
通过不同的策略从不同的文件源读取 BeanDefinition
定义 BeanName 的接口
org.springframework.beans.factory.support#BeanNameGenerator
DefaultBeanNameGenerator
AnnotationBeanNameGenerator
通过不同的方式生成对应 Bean 的名字
获取资源的接口
org.springframework.core.io#ResourceLoader
ClassRelativeResourceLoader
DefaultResourceLoader
FileSystemResourceLoader
ResourcePatternResolver
通过不同的方式获取资源
Composite 模式
org.springframework.cache.support.CompositeCacheManager
组合缓存管理器 CompositeCacheManager:
CompositeCacheManager 自己实现了 CacheManager,并将多个 CacheManager 组合到成员变量中,一般用于对多个缓存进行合并,按照同一个缓存方式进行处理
Decorator 模式
org.springframework.cache.transaction#TransactionAwareCacheDecorator
TransactionAwareCacheDecorator 类相当于装饰器模式中的抽象装饰角色,主要用来处理事务缓存
Spring 的 ApplicationContext 中配置所有的 DataSource。这些 DataSource 可能是各种不同类型的, 比如不同的数据库:Oracle、 SQL Server、 MySQL 等, 也可能是不同的数据源。然后 SessionFactory 根据客户的每次请求, 将 DataSource 属性设置成不同的数据源, 以到达切换数据源的目的。
在 spring 的命名体现:Spring 中用到的包装器模式在类名上有两种表现:一种是类名中含有 Wrapper, 另一种是类名中含有Decorator。基本上都是动态地给一个对象添加一些额外的职责,比如
- org.springframework.cache.transaction 包下的 TransactionAwareCacheDecorator 类
- org.springframework.session.web.http 包下的 SessionRepositoryFilter 内部类 SessionRepositoryRequestWrapper
Visitor模式
org.springframework.beans.factory.config#BeanDefinitionVisitor
BeanDefinition 为 Spring Bean 的定义信息,在 Spring 解析完配置后,会生成 BeanDefinition 并且记录下来。下次通过 getBean 获取 Bean 的时候,会通过 BeanDefinition 来实例化具体的 Bean 对象。
Spring 的 BeanDefinitionVisitor 用来访问 BeanDefinition。
抽象元素为 BeanDefinition。对 Bean 的定义信息,比如属性值、构造方法参数或者更具体的实现。
具体元素有 RootBeanDefinition、ChildBeanDefinition、GenericBeanDefinition 等等。
因为没有对访问者进行扩展,所以只有一个具体访问者 BeanDefinitionVisitor
访问的具体调用就是visitor.visitBeanDefinition(bd);
Chain of.Responsibility 模式
org.springframework.web.servlet#HandlerInterceptor
HandlerInterceptor接口在web开发中非常常用,里面有preHandle()、postHandle()、afterCompletion()三个方法,实现这三个方法可以分别在调用”Controller”方法之前,调用”Controller”方法之后渲染”ModelAndView”之前,以及渲染”ModelAndView”之后执行。
org.springframework.aop.framework#JdkDynamicAopProxy
首先获取目标方法所有的拦截器然后在没有拦截器则直接反射调用目标方法,再生成动态代理的责任链,最后根据生成的责任链去执行对应的流程
Facade 模式
org.springframework.core.io#ResourceLoader
在spring容器中该接口提供了一个统一接口用于访问各种资源(如:文件、流、网络url资源等等),相当于Facade的一个资源访问子系统
Mediator 模式
java.util.Timer#schedule
所有的task都放入了Timer类中维护的task队列中。所以Timer就是充当了一个中介者的角色,而task队列内的任务就是具体同事对象。
SpringMVC 中 control 层就相当于中介去管理 View And Modle 层
Observer模式
- 事件:ApplicationEvent 是所有事件对象的父类。ApplicationEvent 继承自 jdk 的 EventObject, 所有的事件都需要继承 ApplicationEvent, 并且通过 source 得到事件源。Spring 也为我们提供了很多内置事件,ContextRefreshedEvent、ContextStartedEvent、ContextStoppedEvent、ContextClosedEvent、RequestHandledEvent。
- 事件监听:ApplicationListener,也就是观察者,继承自 jdk 的 EventListener,该类中只有一个方法 onApplicationEvent。当监听的事件发生后该方法会被执行。
- 事件源:ApplicationContext,ApplicationContext 是 Spring 中的核心容器,在事件监听中 ApplicationContext 可以作为事件的发布者,也就是事件源。因为 ApplicationContext 继承自 ApplicationEventPublisher。在 ApplicationEventPublisher 中定义了事件发布的方法:publishEvent(Object event)
- 事件管理:ApplicationEventMulticaster,用于事件监听器的注册和事件的广播。监听器的注册就是通过它来实现的,它的作用是把 Applicationcontext 发布的 Event 广播给它的监听器列表。
广播上下文事件,由监听器进行监听处理
Memento 模式
备忘录模式在框架源码中的应用是比较少的,主要还是结合具体的应用场景来使用。 在Spring的Webflow源码中找到一个StateManageableMessageContext接口,我们看到有一个 createMessagesMemento()方法,创建一个消息备忘录
State 模式
Spring中的提供一个组件名称就叫作状态机(StateMachine),状态机帮助开发者简化状态控制的开发过程,让状态机结构更加层次化。
Flyweight Pattern 模式
享元模式,JDK 中对象池的运用(String,Integer,Long….)
Spring Bean工厂中存储 Bean 对象的集合
数据连接池(Data Source Pool)
Proxy 模式
Command 模式
org.springframework.jdbc.core#JdbcTemplate
- StatementCallback 接口 ,类似命令接口(Command)
- class QueryStatementCallback implements StatementCallback
, SqlProvider , 匿名内部类, 实现了命令接口, 同时也充当命令接收者 - 命令调用者 是 JdbcTemplate , 其中 execute(StatementCallback
action) 方法中,调用 action.doInStatement 方法. 不同的 实现 StatementCallback 接口的对象,对应不同的 doInStatemnt 实现逻辑 - 另外实现 StatementCallback 命令接口的子类还有 QueryStatementCallback
Interpreter 模式
org.springframework.expression#ExpressionParser
在 Spring 中,ExpressionParser 接口内部采用的也是解释器模式,它封装了字符串表达式的语法