Spring 中的设计模式
简单工厂
BeanFactory。Spring中的BeanFactory就是简单工厂模式的体现,根据传入一个唯一的标识来获得Bean对象,但是否是在传入参数后创建还是传入参数前创建这个要根据具体情况来定。
工厂方法
FactoryBean接口 Spring会在使用getBean()调用获得该bean时,会自动调用该bean的getObject()方法,所以返回的不是factory这个bean,而是这个bean.getOjbect()方法的返回值。
典型的例子有spring与mybatis的结合 因为实现了 FactoryBean 接口,所以返回的不是 SqlSessionFactoryBean 的实例,而是它的 SqlSessionFactoryBean.getObject() 的返回值。
单例模式
Spring依赖注入Bean实例默认是单例的。
Spring的依赖注入(包括lazy-init方式)都是发生在AbstractBeanFactory的getBean里。getBean的doGetBean方法调用getSingleton进行bean的创建。
Spring 中的单例模式只提供了全局的访问点 BeanFactory。但没有从构造器私有化去控制单例,这是因为 Spring 管理的是任意的 Java 对象。
适配器模式
SpringMVC 中的适配器 HandlerAdatper。
DispatcherServlet 根据 HandlerMapping 返回的 handler,找到对应的 HandlerAdatper 发起请求。
|
|
HandlerAdapter 返回一个 ModelAndView,最后由HandlerAdapter向DispatchServelet返回一个ModelAndView。通过 ViewResolver 找到 View 然后渲染试图。
装饰器模式
Spring中用到的包装器模式在类名上有两种表现:一种是类名中含有Wrapper,另一种是类名中含有Decorator。
动态地给一个对象添加一些额外的职责。
就增加功能来说,Decorator模式相比生成子类更为灵活。
代理模式
实现方式:AOP底层,就是动态代理模式的实现。
观察者模式
Spring 的事件驱动模型使用的是观察者模式 ,Spring 中 Observer 模式常用的地方是 listener 的实现。
事件机制的实现需要三个部分,事件源,事件,事件监听器
ApplicationEvent抽象类[事件] 继承自jdk的EventObject,所有的事件都需要继承ApplicationEvent,并且通过构造器参数source得到事件源.
该类的实现类ApplicationContextEvent表示ApplicaitonContext的容器事件.
ApplicationListener接口[事件监听器] 继承自 jdk 的 EventListener,所有的监听器都要实现这个接口。
这个接口只有一个onApplicationEvent()方法,该方法接受一个ApplicationEvent或其子类对象作为参数,在方法体中,可以通过不同对Event类的判断来进行相应的处理。
当事件触发时所有的监听器都会收到消息。
ApplicationContext接口[事件源] 是 Spring 中的全局容器,翻译过来是”应用上下文”。实现了 ApplicationEventPublisher 接口。
策略模式
Spring框架的资源访问Resource接口。该接口提供了更强的资源访问能力,Spring 框架本身大量使用了 Resource 接口来访问底层资源。
Resource 接口本身没有提供访问任何底层资源的实现逻辑,针对不同的底层资源,Spring 将会提供不同的 Resource 实现类,不同的实现类负责不同的资源访问逻辑。
Spring 为 Resource 接口提供了如下实现类:
- UrlResource: 访问网络资源的实现类。
- ClassPathResource: 访问类加载路径里资源的实现类。
- FileSystemResource: 访问文件系统里资源的实现类。
- ServletContextResource: 访问相对于 ServletContext 路径里的资源的实现类.
- InputStreamResource: 访问输入流资源的实现类。
- ByteArrayResource: 访问字节数组资源的实现类。
这些 Resource 实现类,针对不同的的底层资源,提供了相应的资源访问逻辑,并提供便捷的包装,以利于客户端程序的资源访问。
模版方法模式
经典模板方法定义:父类定义了骨架(调用哪些方法及顺序),某些特定方法由子类实现。
最大的好处:代码复用,减少重复代码。除了子类要实现的特定方法,其他方法及方法调用顺序都在父类中预先写好了。
所以父类模板方法中有两类方法:
-
共同的方法: 所有子类都会用到的代码
-
不同的方法: 子类要覆盖的方法,分为两种:
- 抽象方法:父类中的是抽象方法,子类必须覆盖
- 钩子方法:父类中是一个空方法,子类继承了默认也是空的
注:为什么叫钩子,子类可以通过这个钩子(方法),控制父类,因为这个钩子实际是父类的方法(空方法)!
JdbcTempalte 就是模板方法模式与相应的Callback接口相结合。
一般模板都需要用到继承,因为这个类的方法太多,可以把变化的东西抽出来作为一个参数传入 JdbcTemplate 的方法中。 如果 JdbcTemplate 是抽象类,我们每次进行数据访问的时候都要给出一个相应的子类实现,这样肯定不方便,所以就引入了回调。