0
点赞
收藏
分享

微信扫一扫

谈谈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

​​多线程在Spring中的使用_CBeann的博客​​

适配器模式

   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 {

}
}

 装饰者模式

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

​​(10)spring常用模式--------装饰者模式 - 简书​​

参考

​​面试官:“谈谈Spring中都用到了那些设计模式?”。​​

​​Spring中用到了哪些设计模式? - murphy_gb ​​

​​controller的三种实现方式_chuhuai8266的博客-​​

​​(10)spring常用模式--------装饰者模式 - ​​


举报

相关推荐

0 条评论