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 代码的情况下扩展了它的功能。

  • 25
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值