:::info 🚀 总览
- 简单工厂模式
- 工厂方法模式
- 模板方法模式
- 单例模式
- 代理模式
- 策略模式
- 观察者模式
- 适配器模式
- 装饰器模式 :::
简单工厂模式
实现方式BeanFactory
。Spring中的BeanFactory
就是简单工厂模式的体现,根据传入的beanName
来获得Bean对象,先从缓存中获取,但是在传入参数后创建还是传入参数后创建这个要根据具体情况来定。
实质
由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类。
工厂方法模式
实现方式FactoryBean
接口。
实现原理
实现了FactoryBean
接口的Bean是一类叫做Factory的Bean。其特定是,Spring会在使用getBean()
调用时获得该Bean时,会自动调用该Bean的getObject()
方法,所以返回的不是这个Bean,而是这个Bean的getObject()
方法的返回值。
模板方法模式
实现方式
Spring中的JdbcTemplate、RedisTemplate等以Template结尾的对中间件操作的类,使用的就是模板方法模式与回调模式的结合。
具体实现
采用模板方法模式是为了以一种统一而集中的方式来处理资源的获取和释放。
引入回调原因:JdbcTemplate是抽象类,不能够独立使用,每次进行数据访问的时候都要给出一个相应的子类实现,这样不方便,于是引入了回调。
单例模式
实现方式
spring依赖注入Bean实例默认是单例的。
实现原理
获取Bean的入口是AbstractBeanFactory
的getBean
方法,调用doGetBean
方法,里面使用getSinleton
从三级缓存中获取bean实例:
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
// 这里是经典的DCL(双重检查锁)
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 从一级缓存中获取bean
Object singletonObject = this.singletonObjects.get(beanName);
// 一级缓存中的bean为空,且当前bean正在创建
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 加锁
synchronized (this.singletonObjects) {
// 从二级缓存中获取bean
singletonObject = this.earlySingletonObjects.get(beanName);
// 二级缓存中的bean为空,且允许提前创建
if (singletonObject == null && allowEarlyReference) {
// 从三级缓存中获取对应的ObjectFactory
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
// ObjectFactory不为空
if (singletonFactory != null) {
// 从单例工厂中获取bean
singletonObject = singletonFactory.getObject();
// 添加到二级缓存
this.earlySingletonObjects.put(beanName, singletonObject);
// 从三级缓存中删除
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
...
}
使用双重检查锁保证容器中只存在一个单例Bean。
代理模式
实现方式
Spring AOP的底层,使用动态代理。
对于实现非空接口的对象使用JDK Proxy,默认使用CGlib Proxy。
实现原理
静态代理:手动编写代理类。
动态代理:内存构建。
对比
Spring AOP和Aspect Aop的区别:
- Spring AOP属于运行时增强,AspectJ是编译时增强。
- Spring AOP基于代理,AspectJ基于对class的字节码操作。
- 切面过多时,应该选择AspectJ,性能会好很多。
策略模式
实现方式
Spring框架的资源访问Resource
接口,该接口提供了更强的资源访问能力,Spring框架本身大量使用了Resource
接口来访问底层资源。
具体实现Reource
接口主要包含以下方法:
getInputStream()
:定位并打开资源,返回资源对应的输入流。exists()
:返回Resource所指向的资源是否存在。isOpen()
:返回资源是否打开,如果资源文件不能多次读取,每次读取结束应该显示关闭,以防止资源泄露。getDescription()
:返回资源的描述信息,通常用于资源处理出错时输出该信息,通常是全限定文件名或者实际URI。getFile()
:返回资源对应的File对象。getURL()
:返回资源对应的URL对象。
针对不同的资源,Resource将会提供不同的Resource实现类,不同的实现类负责不同的资源访问逻辑。
Spring为Resource接口
提供了如下实现类:
UrlResource
:访问网络资源。ClassPathResource
:访问类加载路径资源。FileSystemResource
:访问文件系统里资源。ServletContextResource
:访问相对于ServletContext路径里的资源。InputStreamResource
:访问输入流资源。ByteArrayResource
:访问资源数组资源。
观察者模式
实现方式
Spring的事件驱动模型。
具体实现
(1)事件角色ApplicationContext
充当事件的角色,是一个继承java.util.EventObject
抽象类。
Spring中默认存在以下事件,它们都是对ApplicationContextEvent
的实现类:
ContextStartedEvent
:ApplicationContext
启动后触发的事件;ContextStoppedEvent
:ApplicationContext
停止后触发的事件;ContextRefreshedEvent
:ApplicationContext
初始化或刷新完成后触发的事件;ContextClosedEvent
:ApplicationContext
关闭后触发的事件。
(2)事件监听者角色AppicationListener
充当事件监听者角色:
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E event);
}
函数式接口,只需要实现onApplicationContext
即可完成事件监听。
(3)事件发布者角色ApplicationEventPublisher
充当事件发布者角色:
@FunctionalInterface
public interface ApplicationEventPublisher {
void publishEvent(Object event);
}
函数式接口,publishEvent()
这个方法在AbstractApplicationContext
类中被实现,事件实际上是通过ApplicationEventMulticaster
来广播出去的。
适配器模式
实现方式
SpringMVC中的适配器HandlerAdapter。
实现原理
HandlerAdapter根据Handler规则执行不同的Handler。
(1)请求发送到前端控制器DispatcherServlet。
(2)DispatcherServlet收到请求调用HandlerMapping处理器映射器。
(3)处理器映射器找到具体的处理器,生成处理器对象及处理器拦截器一并返回给DispatcherServlet。
(4)DispatcherServlet调用HandlerAdapter处理器适配器。
(5)HandlerAdapter经过适配调用具体的处理器Controller。
(6)Controller执行完成返回ModelAndView。
(7)HandlerAdapter将Controller执行结果ModelAndView返回给DispatcherServlet。
(8)DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
(9)ViewReslover解析后返回具体View。
(10)DispatcherServlet根据View进行渲染视图。
(11)DispatcherServlet响应用户。
装饰器模式
实现方式
Spring中的两种体现:类名后缀为Wrapper或者Decorator。
动态切换数据源,如AtomikosXADataSourceWrapper
。
实质
动态地给对象添加一些额外的职责。