Spring中使用的设计模式

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


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

Java单例模式

Java原型模式(prototype)

Java模板模式(template)

Java观察者模式(Observer)

Java工厂模式

Java适配器模式(adapter)

Java装饰者模式(decorator)

Java代理模式

Java策略模式(Strategy)

文章目录

   Spring使用的设计模式

       1.单例模式

       2.原型模式

       3.模板模式

       4.观察者模式

       5.工厂模式

           简单工厂模式

           工厂方法模式

       6.适配器模式

       7.装饰者模式

       8.代理模式

       9.策略模式

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方法中

image.png

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的步骤是固定的(

   加载驱动,

   获取连接通道,

   构建sql语句.

   执行sql语句,

   关闭资源),

 在这些步骤中第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 {
    @Override
    public 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);
      }
    }
    @Override
    public 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.xsd
    http://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>

image.png

6.适配器模式

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

class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
  @Override
  public boolean supportsAdvice(Advice advice) {
    return (advice instanceof MethodBeforeAdvice);
  }
  @Override
  public 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<?>>() {
              @Override
              public 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);
  }
}


相关文章
|
1月前
|
设计模式 SQL Java
Spring中的设计模式
Spring中的设计模式
|
10天前
|
设计模式 安全 Java
【初学者慎入】Spring源码中的16种设计模式实现
以上是威哥给大家整理了16种常见的设计模式在 Spring 源码中的运用,学习 Spring 源码成为了 Java 程序员的标配,你还知道Spring 中哪些源码中运用了设计模式,欢迎留言与威哥交流。
|
21天前
|
设计模式 Java 数据库连接
Spring Framework 6 中的设计模式
Spring Framework 6 中的设计模式
22 1
|
2月前
|
设计模式 Java 数据库连接
Spring 中经典的 9 种设计模式
Spring 中经典的 9 种设计模式
55 2
|
2月前
|
设计模式 Java 数据库连接
9种设计模式在Spring中的运用
9种设计模式在Spring中的运用
80 0
|
设计模式 Java 数据库连接
Spring设计模式(一)
Spring设计模式(一)
|
7月前
|
设计模式 缓存 Java
Spring 框架中都用到了哪些设计模式
Spring框架采用了多种设计模式来实现自己的功能,这主要是为了解决一些常见的软件开发问题。以下是一些Spring框架中使用设计模式的原因:
30 0
|
4月前
|
设计模式 Java Spring
Spring5深入浅出篇:Spring工厂设计模式拓展应用
Spring5深入浅出篇:Spring工厂设计模式拓展应用
|
4月前
|
设计模式 Java Spring
Spring5深入浅出篇:Spring与工厂设计模式简介
Spring5深入浅出篇:Spring与工厂设计模式简介
|
5月前
|
Java 应用服务中间件 数据库连接
太厉害!Redis+Nginx+设计模式+Spring全家桶+Dubbo技术精选合集
最近花了很长的时间去搜罗Java核心技术好文,我把每个Java核心技术的优选文章都整理成了一个又一个的文档。昨天也是终于全部整理好了,今天就把这些东西分享给老铁们,也能为老铁们省去不少麻烦,想学什么技能了,遇到哪方面的问题了 直接打开文档学一学就好了。不多bb了,直接上干货!