Spring中设计模式详解

1. 工厂设计模式

Spring使用工厂模式可以通过BeanFactory或ApplicationContext创建bean对象

两者对比:

**BeanFactory:**延迟注入(使用到某个bean的时候才会注入),相比与ApplicationContext来说会占用更少的内存,程序启动更快。

**ApplicationContext:**容器启动的时候,不管你用没用到,一次性创建所有的bean。BeanFactory仅提供了最基本的依赖注入支持,ApplicationContext扩展了BeanFactory,除了有BeanFactory的功能还有额外更多功能。

ApplicationContext的三个实现类

1.ClassPathXmlApplication:把上下文文件当成类路径资源

2.FileSystemXmlApplication:从文件系统中的XML文件载入上下文定义信息。

3.XmlWebApplicationContext:从Web系统中的XML文件载入上下文定义。

2.单例设计模式

在系统中,有一些对象其实只需要一个,比如:线程池、缓存、对话框、注册表、日志对象等。事实上,这一类对象只能有一个实例,如果制造出多个实例就可能会导致一些问题的产生,比如程序的行为异常、资源使用过量、或者不一致性的结果。

使用单例模式的好处:

1.对应频繁使用的对象,可以省略创建对象所花费的时间, 这对于哪些重量级对象而言,是一笔非常可观的系统开销。

2.由于new操作的次数减少,因而对系统内存的使用频率也会降低,这将减轻GC压力,缩短GC停顿时间。

Spring中bean的默认作用域就是单例的,除了单例作用域,Spring中Bean还有下面几种作用域:

**prototype:**每次获取都会创建一个新的bean实例,也就是说,连续getBean()两次,得到的是不同的Bean实例。

request(仅web应用可用): 每一次HTTP请求都会产生一个新的bean(请求bean),该bean仅在当前HTTP request内有效。

session(仅web应用可用): 每一次来自新session的HTTP请求都会产生一个新的bean(会话bean),该bean 仅在当前的HTTP session内有效。

**application/global-session(仅web应用可用):**每个web应用在启动时bean(应用bean),该bean仅在当前应用启动时间内有效。

**websocket(仅web应用可用):**每一次webscoket会话产生一个新的bean。

单例Bean存在线程安全问题吗?

单例Bean存在线程问题,主要是因为多个线程操作同一个对象的时候是存在资源竞争的。

解决方法:

1.在Bean中尽量避免定义可变的成员变量。

2.在类中定义一个ThreadLocal成员变量,将需要的可变成员变量保存在ThreadLocal中

不过大部分Bean的实际都是无状态的,这种情况下,Bean是线程安全的。

3.观察者模式

观察者模式是一种对象行为型模式。它表示的是一种对象与对象之间具有依赖关系,当一个对象发生改变的时候,依赖这个对象的所有对象也会做出反应。Spring 事件驱动模型就是观察者模式很经典的一个应用。Spring 事件驱动模型非常有用,在很多场景都可以解耦我们的代码。比如我们每次添加商品的时候都需要重新更新商品索引,这个时候就可以利用观察者模式来解决这个问题。

Spring事件驱动模型的三种角色:

1.事件角色

ApplicationEvent充当事件的角色,这是一个抽象类,它继承了java.util.EventObject并实现了java.io.Serializable接口。

Spring中默认存在以下事件,他们都是对ApplicationCOntextEvent的实现:

ContextStartedEvent: ApplicationContext启动后触发的事件;

ContextStoppedEvent:ApplicatonContext停止后触发的事件;

ContextRefreshedEvent:ApplicationContext初始化或刷新完成后触发的事件;

COntextClosedEvent:ApplicationCOntext关闭后触发的事件

2.事件监听者角色

ApplicationListener 充当了事件监听者角色,它是一个接口,里面只定义了一个 onApplicationEvent()方法来处理ApplicationEventApplicationListener接口类源码如下,可以看出接口定义看出接口中的事件只要实现了 ApplicationEvent就可以了。所以,在 Spring 中我们只要实现 ApplicationListener 接口的 onApplicationEvent() 方法即可完成监听事件

3.事件发布者角色

ApplicationEventPublisher 充当了事件的发布者,它也是一个接口。ApplicationEventPublisher 接r口的publishEvent()这个方法在AbstractApplicationContext类中被实现,阅读这个方法的实现,你会发现实际上事件真正是通过ApplicationEventMulticaster来广播出去的。

Spring事件流程总结

1.定义一个事件:实现一个继承自ApplicationEvent,并且写相应的构造函数

2.定义一个事件监听者:实现Application接口,重写onApplicationEvent()方法

3.使用事件发布者发布消息:可以通过ApplicationEventPiblisher的publishEvent()方法发布消息

4.适配器模式

适配器模式就是将一个接口转化成客户想要的接口,适配器模式使接口不兼容的那些类可以一起工作

SpringAOP中的适配器模式

我们知道 Spring AOP 的实现是基于代理模式,但是 Spring AOP 的增强或通知(Advice)使用到了适配器模式,与之相关的接口是AdvisorAdapter

Advice 常用的类型有:BeforeAdvice(目标方法调用前,前置通知)、AfterAdvice(目标方法调用后,后置通知)、AfterReturningAdvice(目标方法执行结束后,return 之前)等等。每个类型 Advice(通知)都有对应的拦截器:MethodBeforeAdviceInterceptorAfterReturningAdviceInterceptorThrowsAdviceInterceptor 等等。

Spring 预定义的通知要通过对应的适配器,适配成 MethodInterceptor 接口(方法拦截器)类型的对象(如:MethodBeforeAdviceAdapter 通过调用 getInterceptor 方法,将 MethodBeforeAdvice 适配成 MethodBeforeAdviceInterceptor )。

Spring MVC中的适配器模式

在 Spring MVC 中,DispatcherServlet 根据请求信息调用 HandlerMapping,解析请求对应的 Handler。解析到对应的 Handler(也就是我们平常说的 Controller 控制器)后,开始由HandlerAdapter 适配器处理。HandlerAdapter 作为期望接口,具体的适配器实现类用于对目标类进行适配,Controller 作为需要适配的类。

5.装饰器模式

装饰者模式可以动态地给对象添加一些额外的属性或行为。相比于使用继承,装饰者模式更加灵活。简单点儿说就是当我们需要修改原有的功能,但我们又不愿直接去修改原有的代码时,设计一个 Decorator 套在原有代码外面。其实在 JDK 中就有很多地方用到了装饰者模式,比如 InputStream家族,InputStream 类下有 FileInputStream (读取文件)、BufferedInputStream (增加缓存,使读取文件速度大大提升)等子类都在不修改InputStream 代码的情况下扩展了它的功能。

相关推荐
xoxo-Rachel几秒前
(超级详细!!!)解决“com.mysql.jdbc.Driver is deprecated”警告:详解与优化
java·数据库·mysql
色空大师15 分钟前
23种设计模式
java·开发语言·设计模式
闲人一枚(学习中)15 分钟前
设计模式-创建型-建造者模式
java·设计模式·建造者模式
JH307334 分钟前
Oracle与MySQL中CONCAT()函数的使用差异
数据库·mysql·oracle
博风1 小时前
设计模式:6、装饰模式(包装器)
设计模式
A_cot1 小时前
理解设计模式与 UML 类图:构建稳健软件架构的基石
microsoft·设计模式·简单工厂模式·工厂方法模式·uml
君败红颜1 小时前
设计模式之创建模式篇
设计模式
路有瑶台2 小时前
MySQL数据库学习(持续更新ing)
数据库·学习·mysql
码蜂窝编程官方3 小时前
【含开题报告+文档+PPT+源码】基于SpringBoot+Vue的虎鲸旅游攻略网的设计与实现
java·vue.js·spring boot·后端·spring·旅游
lwprain3 小时前
常用docker应用部署,wordpress、mysql、tomcat、nginx、redis
mysql·docker·tomcat