策略模式在Spring源码中的应用
在 Spring 中,Resource 类是基于策略模式实现的,也是策略模式的典型应用。Resource 类的代码如下。
InstantiationStrategy 负责使用 Bean 类的默认构造函数、带参构造函数或者工厂方法等来实例化 Bean,是一个策略模式的接口。InstantiationStrategy 接口源码如下。
SimpleInstantiationStrategy 类实现了 InstantiationStrategy 接口,是一个简单用于实例化 Bean 的类。该类有一个 instantiationWithMethodInjection 方法,但是实际上这只是个钩子,并非真正支持方法注入功能。
真正支持方法注入功能的是 CglibSubclassingInstantiationStrategy 类,它继承了 SimpleInstantiationStrategy 并覆盖了 instantiationWithMethodInjection 方法。不过使用这个方法必须用到 cglib 类库,它利用 cglib 为 bean 动态生成子类,也就是代理类,在子类中生成方法注入的逻辑,然后使用这个动态生成的子类创建 bean 的实例。
其类图如下。
拓展:上图也说明在实际应用中,多种策略之间可以继承使用。小伙伴们可以把它作为一个参考,在实际业务场景中根据需要来设计。
package org.springframework.core.io; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.net.URL; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import org.springframework.lang.Nullable; public interface Resource extends InputStreamSource { boolean exists(); default boolean isReadable() { return exists(); } default boolean isOpen() { return false; } default boolean isFile() { return false; } URL getURL() throws IOException; URI getURI() throws IOException; File getFile() throws IOException; default ReadableByteChannel readableChannel() throws IOException { return Channels.newChannel(getInputStream()); } long contentLength() throws IOException; long lastModified() throws IOException; Resource createRelative(String relativePath) throws IOException; @Nullable String getFilename(); String getDescription(); }虽然 Resource 接口本身没有提供访问任何底层资源的实现逻辑,但是 Spring 会针对不同的底层资源,提供不同的 Resource 实现类,不同的实现类负责不同的资源访问逻辑,如下所示。
* @see WritableResource
* @see ContextResource
* @see UrlResource
* @see FileUrlResource
* @see FileSystemResource
* @see ClassPathResource
* @see ByteArrayResource
* @see InputStreamResource
InstantiationStrategy 负责使用 Bean 类的默认构造函数、带参构造函数或者工厂方法等来实例化 Bean,是一个策略模式的接口。InstantiationStrategy 接口源码如下。
package org.springframework.beans.factory.support; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.lang.Nullable; public interface InstantiationStrategy { Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) throws BeansException; Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner, Constructor<?> ctor, Object... args) throws BeansException; Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner, @Nullable Object factoryBean, Method factoryMethod, Object... args) throws BeansException; }顶层的策略抽象非常简单,它下面有 SimpleInstantiationStrategy 和 CglibSubclassingInstantiationStrategy 两种策略。
SimpleInstantiationStrategy 类实现了 InstantiationStrategy 接口,是一个简单用于实例化 Bean 的类。该类有一个 instantiationWithMethodInjection 方法,但是实际上这只是个钩子,并非真正支持方法注入功能。
真正支持方法注入功能的是 CglibSubclassingInstantiationStrategy 类,它继承了 SimpleInstantiationStrategy 并覆盖了 instantiationWithMethodInjection 方法。不过使用这个方法必须用到 cglib 类库,它利用 cglib 为 bean 动态生成子类,也就是代理类,在子类中生成方法注入的逻辑,然后使用这个动态生成的子类创建 bean 的实例。
其类图如下。
所有教程
- C语言入门
- C语言编译器
- C语言项目案例
- 数据结构
- C++
- STL
- C++11
- socket
- GCC
- GDB
- Makefile
- OpenCV
- Qt教程
- Unity 3D
- UE4
- 游戏引擎
- Python
- Python并发编程
- TensorFlow
- Django
- NumPy
- Linux
- Shell
- Java教程
- 设计模式
- Java Swing
- Servlet
- JSP教程
- Struts2
- Maven
- Spring
- Spring MVC
- Spring Boot
- Spring Cloud
- Hibernate
- Mybatis
- MySQL教程
- MySQL函数
- NoSQL
- Redis
- MongoDB
- HBase
- Go语言
- C#
- MATLAB
- JavaScript
- Bootstrap
- HTML
- CSS教程
- PHP
- 汇编语言
- TCP/IP
- vi命令
- Android教程
- 区块链
- Docker
- 大数据
- 云计算