Spring使用工厂模式可以通过BeanFactory或ApplicationContext创建bean对象
两者对比:
BeanFactory:延迟注入(使用到某个bean的时候才会注入),相比与ApplicationContext来说会占用更少的内存,程序启动更快。
ApplicationContext:容器启动的时候,不管你用没用到,一次性创建所有的bean。BeanFactory仅提供了最基本的依赖注入支持,ApplicationContext扩展了BeanFactory,除了有BeanFactory的功能还有额外更多功能。
ApplicationContext的三个实现类:
1.ClassPathXmlApplication:把上下文文件当成类路径资源
2.FileSystemXmlApplication:从文件系统中的XML文件载入上下文定义信息。
3.XmlWebApplicationContext:从Web系统中的XML文件载入上下文定义。
在系统中,有一些对象其实只需要一个,比如:线程池、缓存、对话框、注册表、日志对象等。事实上,这一类对象只能有一个实例,如果制造出多个实例就可能会导致一些问题的产生,比如程序的行为异常、资源使用过量、或者不一致性的结果。
使用单例模式的好处:
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是线程安全的。
观察者模式是一种对象行为型模式。它表示的是一种对象与对象之间具有依赖关系,当一个对象发生改变的时候,依赖这个对象的所有对象也会做出反应。Spring 事件驱动模型就是观察者模式很经典的一个应用。Spring 事件驱动模型非常有用,在很多场景都可以解耦我们的代码。比如我们每次添加商品的时候都需要重新更新商品索引,这个时候就可以利用观察者模式来解决这个问题。
Spring事件驱动模型的三种角色:
1.事件角色
ApplicationEvent充当事件的角色,这是一个抽象类,它继承了java.util.EventObject并实现了java.io.Serializable接口。
Spring中默认存在以下事件,他们都是对ApplicationCOntextEvent的实现:
ContextStartedEvent: ApplicationContext启动后触发的事件;
ContextStoppedEvent:ApplicatonContext停止后触发的事件;
ContextRefreshedEvent:ApplicationContext初始化或刷新完成后触发的事件;
COntextClosedEvent:ApplicationCOntext关闭后触发的事件
2.事件监听者角色
ApplicationListener
充当了事件监听者角色,它是一个接口,里面只定义了一个 onApplicationEvent()
方法来处理ApplicationEvent
。ApplicationListener
接口类源码如下,可以看出接口定义看出接口中的事件只要实现了 ApplicationEvent
就可以了。所以,在 Spring 中我们只要实现 ApplicationListener
接口的 onApplicationEvent()
方法即可完成监听事件
3.事件发布者角色
ApplicationEventPublisher
充当了事件的发布者,它也是一个接口。ApplicationEventPublisher
接r口的publishEvent()
这个方法在AbstractApplicationContext
类中被实现,阅读这个方法的实现,你会发现实际上事件真正是通过ApplicationEventMulticaster
来广播出去的。
Spring事件流程总结
1.定义一个事件:实现一个继承自ApplicationEvent,并且写相应的构造函数
2.定义一个事件监听者:实现Application接口,重写onApplicationEvent()方法
3.使用事件发布者发布消息:可以通过ApplicationEventPiblisher的publishEvent()方法发布消息
适配器模式就是将一个接口转化成客户想要的接口,适配器模式使接口不兼容的那些类可以一起工作
SpringAOP中的适配器模式
我们知道 Spring AOP 的实现是基于代理模式,但是 Spring AOP 的增强或通知(Advice)使用到了适配器模式,与之相关的接口是AdvisorAdapter
。
Advice 常用的类型有:BeforeAdvice
(目标方法调用前,前置通知)、AfterAdvice
(目标方法调用后,后置通知)、AfterReturningAdvice
(目标方法执行结束后,return 之前)等等。每个类型 Advice(通知)都有对应的拦截器:MethodBeforeAdviceInterceptor
、AfterReturningAdviceInterceptor
、ThrowsAdviceInterceptor
等等。
Spring 预定义的通知要通过对应的适配器,适配成 MethodInterceptor
接口(方法拦截器)类型的对象(如:MethodBeforeAdviceAdapter
通过调用 getInterceptor
方法,将 MethodBeforeAdvice
适配成 MethodBeforeAdviceInterceptor
)。
Spring MVC中的适配器模式
在 Spring MVC 中,DispatcherServlet
根据请求信息调用 HandlerMapping
,解析请求对应的 Handler
。解析到对应的 Handler
(也就是我们平常说的 Controller
控制器)后,开始由HandlerAdapter
适配器处理。HandlerAdapter
作为期望接口,具体的适配器实现类用于对目标类进行适配,Controller
作为需要适配的类。
装饰者模式可以动态地给对象添加一些额外的属性或行为。相比于使用继承,装饰者模式更加灵活。简单点儿说就是当我们需要修改原有的功能,但我们又不愿直接去修改原有的代码时,设计一个 Decorator 套在原有代码外面。其实在 JDK 中就有很多地方用到了装饰者模式,比如 InputStream
家族,InputStream
类下有 FileInputStream
(读取文件)、BufferedInputStream
(增加缓存,使读取文件速度大大提升)等子类都在不修改InputStream
代码的情况下扩展了它的功能。