谈谈Spring中都用到了那些设计模式

简介: 写作目的看看Spring和SpringMVC源码还是有必要的,而且里面用了很多经典的设计模式,所以从源码角度分析一下Spring中的设计模式。

源码下载


ChaiRongD/Demooo - Gitee.com

ChaiRongD/Demooo - Gitee.com


设计模式


工厂设计模式


Spring使用工厂模式可以通过 ApplicationContext 创建和获取 bean 对象。其实这里就有一个问题,ApplicationContext和BeanFactory有什么关系呢?其实这个问题可以从源码中看出来。


下面是获取ioc容器的context,根据名称获取Bean,这段代码大家都比较熟悉


    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(App.class);
    Student bean = (Student) context.getBean("student");
    bean.speak();


其实你跟跟进去getBean方法,你就会大吃一惊,是核心还是beanFactory。


@Override
  public Object getBean(String name) throws BeansException {
    assertBeanFactoryActive();
    return getBeanFactory().getBean(name);
  }


单例设计模式


  Spring中Bean默认都是单例的,既然是单例的,那存在哪呢,其实是存在一个map里。其实一共使用了三个map,又称作三级缓存


//DefaultSingletonBeanRegistry
  /** 三级缓存(存放的是可以使用的Bean) */
  private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
  /** 一级缓存(存放的是BeanFacory对象) */
  private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
  /** 二级缓存(存放的是经过代理的获取不需要代理的对象,此时对象的属性还有部分没有被填充) */
  private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
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;
  }


虽然Bean是单例的,但是也存在线程不安全的情况。如下面代码所示。


@Controller
public class HelloController {
    int num = 0;
    @GetMapping("add")
    public void add(){
        num++;
    }
}


代理设计模式


  Spring中代理模式中使用的最经典的是AOP,这里跟源码就比较麻烦了,其实这里的知识点有jdk动态代理和cglib代理,这俩有什么区别,经典题。


1 jdk代理的类要有接口,cglib代理则不需要

2 cglib代理的时候生成的代理类生成速度慢,但是调用速度快,jdk反之。


模板方法模式


  在获取context的地方有一个refresh()方法,这个地方就是模版方法模式


AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(App.class);


public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
    this();
    register(annotatedClasses);
    refresh();
  }


观察者模式


观察者模式的一个落地实现是listener,Spring也有Listener


适配器模式


 SpringMVC中有一个核心的servlet就是DispatcherServlet,该方法里有一个Servlet有一个方式是doDispatch,先获取HanderMethod(就是有@GetMapping的方法),然后在获取适配器Adapter,这说明有好几种HanderMethod,其实实现controller有三种方式


protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    HttpServletRequest processedRequest = request;
    HandlerExecutionChain mappedHandler = null;
    boolean multipartRequestParsed = false;
    WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    try {
      ModelAndView mv = null;
      Exception dispatchException = null;
      try {
        processedRequest = checkMultipart(request);
        multipartRequestParsed = (processedRequest != request);
        // 获取handlerMethod,就是我们自己写个@GetMapper的方法
        mappedHandler = getHandler(processedRequest);
        if (mappedHandler == null) {
          noHandlerFound(processedRequest, response);
          return;
        }
        // 获取handlerMethod 的是适配器Adapter
        HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
        // Process last-modified header, if supported by the handler.
        String method = request.getMethod();
        boolean isGet = "GET".equals(method);
        if (isGet || "HEAD".equals(method)) {
          long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
          if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
            return;
          }
        }
        if (!mappedHandler.applyPreHandle(processedRequest, response)) {
          return;
        }
        // Actually invoke the handler.
        mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
        if (asyncManager.isConcurrentHandlingStarted()) {
          return;
        }
        applyDefaultViewName(processedRequest, mv);
        mappedHandler.applyPostHandle(processedRequest, response, mv);
      }
      catch (Exception ex) {
      }
      catch (Throwable err) {
    }
    catch (Exception ex) {
    }
    catch (Throwable err) {
    }
    finally {
    }
  }


装饰者模式


其实我看源码没有看到,主要原因是自己水平还有待提高,所以有些看不太懂,这里找了一篇文章,做为补充。

目录
相关文章
|
5天前
|
设计模式 Java 数据库连接
Spring Framework 6 中的设计模式
Spring Framework 6 中的设计模式
17 1
|
26天前
|
设计模式 Java 数据库连接
9种设计模式在Spring中的运用
9种设计模式在Spring中的运用
63 0
|
设计模式 Java 数据库连接
Spring设计模式(一)
Spring设计模式(一)
|
6月前
|
设计模式 缓存 Java
Spring 框架中都用到了哪些设计模式
Spring框架采用了多种设计模式来实现自己的功能,这主要是为了解决一些常见的软件开发问题。以下是一些Spring框架中使用设计模式的原因:
30 0
|
3月前
|
设计模式 Java Spring
Spring5深入浅出篇:Spring工厂设计模式拓展应用
Spring5深入浅出篇:Spring工厂设计模式拓展应用
|
3月前
|
设计模式 Java Spring
Spring5深入浅出篇:Spring与工厂设计模式简介
Spring5深入浅出篇:Spring与工厂设计模式简介
|
4月前
|
Java 应用服务中间件 数据库连接
太厉害!Redis+Nginx+设计模式+Spring全家桶+Dubbo技术精选合集
最近花了很长的时间去搜罗Java核心技术好文,我把每个Java核心技术的优选文章都整理成了一个又一个的文档。昨天也是终于全部整理好了,今天就把这些东西分享给老铁们,也能为老铁们省去不少麻烦,想学什么技能了,遇到哪方面的问题了 直接打开文档学一学就好了。不多bb了,直接上干货!
|
6月前
|
设计模式 Java Spring
Spring框架中使用了那些设计模式
Spring框架中使用了那些设计模式
25 0
|
6月前
|
设计模式 前端开发 Java
JAVA设计模式第七讲:设计模式在 Spring 源码中的应用
JAVA设计模式第七讲:设计模式在 Spring 源码中的应用
|
7月前
|
设计模式 前端开发 Java
Java经典面试题:Spring中用到了哪些设计模式?
一位应届毕业生被问到这样一道面试题,说Spring用到了哪些设计模式?其实只要Spring使用得够熟练,回答这道题还是非常轻松的。因为Spring的命名非常规范,基本上从类名就可以看得出来用到了哪些设计模式。 今天,我给大家分享一下我的理解。
64 1