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

心已赠人 2022-10-07 04:58 221阅读 0赞

写作目的

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

源码下载

https://gitee.com/cbeann/Demooo/tree/master/spring-demo

https://gitee.com/cbeann/Demooo/tree/master/springmvc-demo-app

设计模式

工厂设计模式

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

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

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

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

  1. @Override
  2. public Object getBean(String name) throws BeansException {
  3. assertBeanFactoryActive();
  4. return getBeanFactory().getBean(name);
  5. }

单例设计模式

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

  1. //DefaultSingletonBeanRegistry
  2. /** 三级缓存(存放的是可以使用的Bean) */
  3. private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
  4. /** 一级缓存(存放的是BeanFacory对象) */
  5. private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
  6. /** 二级缓存(存放的是经过代理的获取不需要代理的对象,此时对象的属性还有部分没有被填充) */
  7. private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
  8. protected Object getSingleton(String beanName, boolean allowEarlyReference) {
  9. //从三级缓存冲获取
  10. Object singletonObject = this.singletonObjects.get(beanName);
  11. if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
  12. synchronized (this.singletonObjects) {
  13. //从二级缓存中获取
  14. singletonObject = this.earlySingletonObjects.get(beanName);
  15. if (singletonObject == null && allowEarlyReference) {
  16. //从一级缓存中获取
  17. ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
  18. if (singletonFactory != null) {
  19. singletonObject = singletonFactory.getObject();
  20. this.earlySingletonObjects.put(beanName, singletonObject);
  21. this.singletonFactories.remove(beanName);
  22. }
  23. }
  24. }
  25. }
  26. return singletonObject;
  27. }

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

  1. @Controller
  2. public class HelloController {
  3. int num = 0;
  4. @GetMapping("add")
  5. public void add(){
  6. num++;
  7. }
  8. }

代理设计模式

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

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

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

模板方法模式

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

  1. AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(App.class);
  2. public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
  3. this();
  4. register(annotatedClasses);
  5. refresh();
  6. }

观察者模式

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

https://blog.csdn.net/qq_37171353/article/details/113940911

适配器模式

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

  1. protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
  2. HttpServletRequest processedRequest = request;
  3. HandlerExecutionChain mappedHandler = null;
  4. boolean multipartRequestParsed = false;
  5. WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
  6. try {
  7. ModelAndView mv = null;
  8. Exception dispatchException = null;
  9. try {
  10. processedRequest = checkMultipart(request);
  11. multipartRequestParsed = (processedRequest != request);
  12. // 获取handlerMethod,就是我们自己写个@GetMapper的方法
  13. mappedHandler = getHandler(processedRequest);
  14. if (mappedHandler == null) {
  15. noHandlerFound(processedRequest, response);
  16. return;
  17. }
  18. // 获取handlerMethod 的是适配器Adapter
  19. HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
  20. // Process last-modified header, if supported by the handler.
  21. String method = request.getMethod();
  22. boolean isGet = "GET".equals(method);
  23. if (isGet || "HEAD".equals(method)) {
  24. long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
  25. if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
  26. return;
  27. }
  28. }
  29. if (!mappedHandler.applyPreHandle(processedRequest, response)) {
  30. return;
  31. }
  32. // Actually invoke the handler.
  33. mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
  34. if (asyncManager.isConcurrentHandlingStarted()) {
  35. return;
  36. }
  37. applyDefaultViewName(processedRequest, mv);
  38. mappedHandler.applyPostHandle(processedRequest, response, mv);
  39. }
  40. catch (Exception ex) {
  41. }
  42. catch (Throwable err) {
  43. }
  44. catch (Exception ex) {
  45. }
  46. catch (Throwable err) {
  47. }
  48. finally {
  49. }
  50. }

装饰者模式

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

https://www.jianshu.com/p/8f6ebeee1ae6

参考

https://zhuanlan.zhihu.com/p/66790602

https://www.cnblogs.com/kyoner/p/10949246.html

https://blog.csdn.net/chuhuai8266/article/details/100757333

https://www.jianshu.com/p/8f6ebeee1ae6

发表评论

表情:
评论列表 (有 0 条评论,221人围观)

还没有评论,来说两句吧...

相关阅读