源码下载
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 { } }
装饰者模式
其实我看源码没有看到,主要原因是自己水平还有待提高,所以有些看不太懂,这里找了一篇文章,做为补充。