Spring框架是每个java程序猿入门级的框架也是最重要的框架,而Spring中也采用了很多的设计模式,这些也会成为我们面试过程中经常会问到的问题,所以本文就整理出Spring中具体使用的哪些设计模式。 Spring使用的设计模式

1.单例模式

单例模式应该是大家印象最深的一种设计模式了。在Spring中最明显的使用场景是在配置文件中配置注册bean对象的时候设置scope的值为singleton。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean class="com.dpb.pojo.User" id="user" scope="singleton"><property name="name" value="波波烤鸭"></property></bean>
</beans>
复制代码

源码实现:AbstractBeanFactory的getBean方法中

protected Object getSingleton(String beanName, boolean allowEarlyReference) {Object singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {synchronized (this.singletonObjects) {singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null && allowEarlyReference) {ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);if (singletonFactory != null) {singletonObject = singletonFactory.getObject();this.earlySingletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);}}}}return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
复制代码

双重判断加锁的实现!!!

2.原型模式

原型模式也叫克隆模式,Spring中该模式使用的很明显,和单例一样在bean标签中设置scope的属性为prototype即表示该bean以克隆的方式生成

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean class="com.dpb.pojo.User" id="user" scope="prototype"><property name="name" value="波波烤鸭"></property></bean>
</beans>
复制代码

3.模板模式

模板模式的核心是父类定义好流程,然后将流程中需要子类实现的方法就抽象话留给子类实现,Spring中的JdbcTemplate就是这样的实现。我们知道jdbc的步骤是固定的(

加载驱动,

  1. 获取连接通道,
  2. 构建sql语句.
  3. 执行sql语句,
  4. 关闭资源,   在这些步骤中第3步和第四步是不确定的,所以就留给客户实现,而我们实际使用JdbcTemplate的时候也确实是只需要构建SQL就可以了.这就是典型的模板模式。我们以query方法为例来看下JdbcTemplate中的代码
// 在execute方法中定义好了jdbc操作的流程
// action.doInStatement(stmtToUse);是回调方法也就是钩子
@Override
public <T> T execute(StatementCallback<T> action) throws DataAccessException {Assert.notNull(action, "Callback object must not be null");Connection con = DataSourceUtils.getConnection(getDataSource());Statement stmt = null;try {Connection conToUse = con;if (this.nativeJdbcExtractor != null &&this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativeStatements()) {conToUse = this.nativeJdbcExtractor.getNativeConnection(con);}stmt = conToUse.createStatement();applyStatementSettings(stmt);Statement stmtToUse = stmt;if (this.nativeJdbcExtractor != null) {stmtToUse = this.nativeJdbcExtractor.getNativeStatement(stmt);}T result = action.doInStatement(stmtToUse);handleWarnings(stmt);return result;}catch (SQLException ex) {// Release Connection early, to avoid potential connection pool deadlock// in the case when the exception translator hasn't been initialized yet.JdbcUtils.closeStatement(stmt);stmt = null;DataSourceUtils.releaseConnection(con, getDataSource());con = null;throw getExceptionTranslator().translate("StatementCallback", getSql(action), ex);}finally {JdbcUtils.closeStatement(stmt);DataSourceUtils.releaseConnection(con, getDataSource());}
}
复制代码

query方法

@Override
public <T> T query(final String sql, final ResultSetExtractor<T> rse) throws DataAccessException {Assert.notNull(sql, "SQL must not be null");Assert.notNull(rse, "ResultSetExtractor must not be null");if (logger.isDebugEnabled()) {logger.debug("Executing SQL query [" + sql + "]");}// 实现模板中预留的功能class QueryStatementCallback implements StatementCallback<T>, SqlProvider {@Overridepublic T doInStatement(Statement stmt) throws SQLException {ResultSet rs = null;try {// 此处具体执行查询操作rs = stmt.executeQuery(sql);ResultSet rsToUse = rs;if (nativeJdbcExtractor != null) {rsToUse = nativeJdbcExtractor.getNativeResultSet(rs);}// 处理数据封装操作return rse.extractData(rsToUse);}finally {JdbcUtils.closeResultSet(rs);}}@Overridepublic String getSql() {return sql;}}return execute(new QueryStatementCallback());
}
复制代码

4.观察者模式

观察者模式定义的是对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。使用比较场景是在监听器中而spring中Observer模式常用的地方也是listener的实现。如ApplicationListener。 Spring中的事件监听请参考我的另一篇文章 Spring之事件监听(观察者模型)

5.工厂模式

简单工厂模式

简单工厂模式就是通过工厂根据传递进来的参数决定产生哪个对象。Spring中我们通过getBean方法获取对象的时候根据id或者name获取就是简单工厂模式了。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"><context:annotation-config/><bean class="com.dpb.pojo.User" id="user"  ><property name="name" value="波波烤鸭"></property></bean>
</beans>
复制代码

工厂方法模式

在Spring中我们一般是将Bean的实例化直接交给容器去管理的,实现了使用和创建的分离,这时容器直接管理对象,还有种情况是,bean的创建过程我们交给一个工厂去实现,而Spring容器管理这个工厂。这个就是我们讲的工厂模式,在Spring中有两种实现一种是静态工厂方法模式,一种是动态工厂方法模式。以静态工厂来演示

/*** User 工厂类* @author dpb[波波烤鸭]**/
public class UserFactory {/*** 必须是static方法* @return*/public static UserBean getInstance(){return new UserBean();}
}
复制代码

application.xml文件中注册

<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 静态工厂方式配置 配置静态工厂及方法 --><bean class="com.dpb.factory.UserFactory" factory-method="getInstance" id="user2"/>
</beans>
复制代码

6.适配器模式

将一个类的接口转换成客户希望的另外一个接口。使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。这就是适配器模式。在Spring中在AOP实现中的Advice和interceptor之间的转换就是通过适配器模式实现的。

class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {@Overridepublic boolean supportsAdvice(Advice advice) {return (advice instanceof MethodBeforeAdvice);}@Overridepublic MethodInterceptor getInterceptor(Advisor advisor) {MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();// 通知类型匹配对应的拦截器return new MethodBeforeAdviceInterceptor(advice);}
}
复制代码

详细介绍可以参考此文Spring之AOP适配器模式

7.装饰者模式

装饰者模式又称为包装模式(Wrapper),作用是用来动态的为一个对象增加新的功能。装饰模式是一种用于代替继承的技术,无须通过继承增加子类就能扩展对象的新功能。使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀。   spring中用到的包装器模式在类名上有两种表现:一种是类名中含有Wrapper,另一种是类名中含有Decorator。基本上都是动态地给一个对象添加一些额外的职责。   具体的使用在Spring session框架中的SessionRepositoryRequestWrapper使用包装模式对原生的request的功能进行增强,可以将session中的数据和分布式数据库进行同步,这样即使当前tomcat崩溃,session中的数据也不会丢失。

查看需要的maven依赖

<dependency><groupId>org.springframework.session</groupId><artifactId>spring-session</artifactId><version>1.3.1.RELEASE</version>
</dependency>
复制代码

8.代理模式

代理模式应该是大家非常熟悉的设计模式了,在Spring中AOP的实现中代理模式使用的很彻底,如果不了解代理模式欢迎查看我之前的文章,链接在顶部。

9.策略模式

策略模式对应于解决某一个问题的一个算法族,允许用户从该算法族中任选一个算法解决某一问题,同时可以方便的更换算法或者增加新的算法。并且由客户端决定调用哪个算法,spring中在实例化对象的时候用到Strategy模式。

@Override
public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {// Don't override the class with CGLIB if no overrides.if (bd.getMethodOverrides().isEmpty()) {Constructor<?> constructorToUse;synchronized (bd.constructorArgumentLock) {constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;if (constructorToUse == null) {final Class<?> clazz = bd.getBeanClass();if (clazz.isInterface()) {throw new BeanInstantiationException(clazz, "Specified class is an interface");}try {if (System.getSecurityManager() != null) {constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {@Overridepublic Constructor<?> run() throws Exception {return clazz.getDeclaredConstructor((Class[]) null);}});}else {constructorToUse =    clazz.getDeclaredConstructor((Class[]) null);}bd.resolvedConstructorOrFactoryMethod = constructorToUse;}catch (Throwable ex) {throw new BeanInstantiationException(clazz, "No default constructor found", ex);}}}return BeanUtils.instantiateClass(constructorToUse);}else {// Must generate CGLIB subclass.return instantiateWithMethodInjection(bd, beanName, owner);}
}
复制代码

转载于:https://juejin.im/post/5cb9ca94f265da0387339c6f

Spring中使用的九种设计模式相关推荐

  1. 详解spring用到的九种设计模式

    转载请注明出处,文章首发于:http://www.itxxz.com/a/javashili/tuozhan/2014/0601/7.html 设计模式作为工作学习中的枕边书,却时常处于勤说不用的尴尬 ...

  2. Spring中用到的九种设计模式

    spring中常用的设计模式达到九种,我们举例说明: 第一种:简单工厂 又叫做静态工厂方法(StaticFactory Method)模式,但不属于23种GOF设计模式之一.  简单工厂模式的实质是由 ...

  3. Spring 中经典的 9 种设计模式,打死也要记住啊!

    点击上方 好好学java ,选择 星标 公众号重磅资讯,干货,第一时间送达今日推荐:分享一套基于SpringBoot和Vue的企业级中后台开源项目,这个项目有点哇塞!个人原创100W +访问量博客:点 ...

  4. controller调用另一个controller中的方法 获取返回值_必须掌握!你知道 Spring 中运用的 9 种设计模式吗 ?...

    Spring中涉及的设计模式总结,在面试中也会经常问道 Spring 中设计模式的问题.本文以实现方式.实质.实现原理的结构简单介绍 Sping 中应用的 9 种设计模型,具体详细的刨析会在后面的文章 ...

  5. Spring/SpringBoot系列之Spring中涉及的9种设计模式【七】

    1. 总览 Spring中涉及的设计模式: 简单工厂(非23种设计模式中的一种) 工厂方法 单例模式 适配器模式 装饰器模式 代理模式 观察者模式 策略模式 模版方法模式 2. 详细介绍 2.1 简单 ...

  6. 必须掌握!你知道 Spring 中运用的 9 种设计模式吗 ?

    点击上方 "程序员小乐"关注, 星标或置顶一起成长 后台回复"大礼包"有惊喜礼包! 关注订阅号「程序员小乐」,收看更多精彩内容 每日英文 Although yo ...

  7. 【设计模式】Spring 中经典的 9 种设计模式

    前言 控制反转(IoC)和依赖注入(DI) IoC(Inversion of Control,控制翻转) 是Spring 中一个非常非常重要的概念,它不是什么技术,而是一种解耦的设计思想.它的主要目的 ...

  8. Spring中经典的9种设计模式,一定要记牢,Java基础教程pdf百度云

    实现原理: HandlerAdatper根据Handler规则执行不同的Handler. 实现过程: DispatcherServlet根据HandlerMapping返回的handler,向Hand ...

  9. Spring中用到的九种设计模式五:模板模式

    系列文章目录 文章目录 系列文章目录 前言 一.模板模式 二.主要角色 1. AbstractTemplate(抽象模板): 2. ConcreteTemplate(具体模板): 三.代码实现与示例 ...

  10. Spring主要用到两种设计模式

    Spring主要用到两种设计模式 1.工厂模式 Spring容器就是实例化和管理全部Bean的工厂. 工厂模式可以将Java对象的调用者从被调用者的实现逻辑中分离出来. 调用者只关心被调用者必须满足的 ...

最新文章

  1. vbs之CurrentDirectory
  2. 边缘检测算法及各自优缺点
  3. 基于RTP的h.264视频传输系统(二)
  4. 用Javascript隐藏超级链接的真实地址
  5. java技术_JAVA-JDBC技术
  6. boost--线程同步
  7. Python 单元测试详解
  8. Java Swing专栏订阅须知《必读》
  9. Javascript——声明提升(函数、变量提升)
  10. [python] 线程锁
  11. 利用Office加载项进行持久化控制的6种姿势
  12. eclipse下properties配置文件中文乱码解决
  13. 捷联惯导系统学习2.2(方向余弦)
  14. Typora数学公式大全
  15. Protues8.6仿真STM32出现错误-VDDA和VSSA的问题解决办法
  16. Wintel机器代码反反转练习(C/C++逆向)
  17. 深入浅出matplotlib(1):为什么要使用matplotlib
  18. java五子棋AI算法人机对战(春物彩羽版可下载试玩PC端)
  19. 我的世界java版1.7.10咋刷物品,1.7指令方块刷自定义药水教程
  20. C语言 五种基本的算术运算符

热门文章

  1. 网盘纷纷“隐退” 云存储仍是刚需
  2. 虚拟机中centos7 安装过程中没有自动获取到网络
  3. 算法分析-堆排序 HeapSort 优先级队列
  4. json学习初体验--第三者jar包实现bean、List、map创json格式
  5. 信号量函数(semget、semop、semctl)
  6. Android.mk 语法详解
  7. SylixOS arm64 异常向量表
  8. TI TMS570LC43xx 裸机开发快速上手
  9. qt 写的tcp客户端程序实现简单的连接接受和发送消息
  10. 解决PLSQL和输入法或QQ冲突问题