适配器模式在 JDK 及 spring 源码中的引用

适配器模式

适配器模式是一种结构型设计模式, 它能使接口不兼容的对象能够相互合作。

适配器模式在 spring 源码中的应用:DisposableBeanAdapter

当 spring 容器启动时,会将所有 “DisposableBean” 添加到 disposableBeans 集合,可能有各种类,比如:

  • 通过 @Bean 注入的实现了 close 方法的 UserService、
  • 实现了 DisposableBean 接口,重写了 destory() 方法的类、
  • 实现了 AutoCloseable 接口的类
  • ……

关闭容器销毁单例 Bean 时,Spring 会找出实现了 “DisposableBean”,并执行对应的方法,进行 Bean 的销毁。这就需要进行很多判断:

  • 如果是实现了 close() 方法的 DisposableBean,就调用 close() 方法销毁
  • 如果是实现了 DisposableBean 的类,就调用 destory() 方法销毁
  • 如果是… 就…

所以对外提供了一个适配器:DisposableBeanAdapter,将这些判断封装起来,外部使用者直接调用 DisposableBeanAdapter 的 destory() 方法即可,在里面会判断到底去调用 close 方法,还是 destroy 方法,或者其他。这就是适配器模式

DisposableBeanAdapter#destroy

org.springframework.beans.factory.support.DisposableBeanAdapter#destroy

@Override
public void destroy() {// beanif (!CollectionUtils.isEmpty(this.beanPostProcessors)) {// 执行 @PreDestroy 注解指定的销毁方法for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {processor.postProcessBeforeDestruction(this.bean, this.beanName);}}// 如果当前类实现了 DisposableBeanif (this.invokeDisposableBean) {if (logger.isTraceEnabled()) {logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'");}try {if (System.getSecurityManager() != null) {// 执行 DisposableBean 的 destroy 方法AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {((DisposableBean) this.bean).destroy();return null;}, this.acc);}else {((DisposableBean) this.bean).destroy();}}catch (Throwable ex) {String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";if (logger.isDebugEnabled()) {logger.warn(msg, ex);}else {logger.warn(msg + ": " + ex);}}}// 如果指定了 destroyMethod,则执行if (this.destroyMethod != null) {invokeCustomDestroyMethod(this.destroyMethod);}else if (this.destroyMethodName != null) {Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);if (methodToInvoke != null) {invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));}}
}

Bean 的生命周期

  • 加载类
  • 实例化前
  • 实例化
  • BeanDefinition 后置处理
    • CommonAnnotationBeanPostProcessor:找 @PostConstruct 和 @PreDestroy 修饰的方法
  • 实例化后
  • 填充属性
  • 初始化前—BeanPostProcessor.postProcessBeforeInitialization
    • (执行 @PostConstruct 定义的方法)
  • 初始化:创建 Bean
  • 初始化后—BeanPostProcessor
    • 判断 Bean 是否是 DisposableBean,如果是则加入到 disposableBeans<beanName, new
      DisposableBeanAdapter(bean)> 中
      • 是否实现了 DisposableBean 接口
      • 实现了AutoCloseable 接口
      • BeanDefinition 中定义了 destroyMethodName
      • 如果 destroy-method 为默认值则看是否定义了 close 和 shutdown 方法
      • 类中是否存在@PreDestroy 注解的方法
  • Bean 的销毁
    • 当调用 applicationContext.close() 时,执行 disposableBeans
      中所有的 DisposableBeanAdapter 对应的销毁方法 destroy。(DisposableBeanAdapter
      实现了 DisposableBean 接口,重写了 destroy 方法逻辑如下)
      • 执行 @PreDestroy 修饰的方法。
      • 当前类实现了 DisposableBean 接口,则强转为 DisposableBean 类型,然后执行 destroy 方法。
      • 如果指定了 destroy-method,则执行。(destroy-method 有优先级如下)
        • 实现了 AutoCloseable 接口,就把它的 close 方法作为 destroy-method。
        • 如果指定了 destroyMethodName,把指定的作为 destroy-method。
        • 如果指定的 destroyMethodName 为默认值,如果定义了 close 方法,把 close 方法作为 destroy-method。
        • 如果没有 close,看是否有 shutdown 方法,如果有,把它作为 destroy-method。

适配器模式在 springmvc 源码中的应用:HeandlerAdapter

springmvc 支持多种类型的处理器

  1. 自定义类加上 @Controller 注解,自定义方法加上 @RequestMapping 注解。
  2. 自定义类实现 Servlet 接口(一般都直接实现 HttpServlet 接口)。
  3. 自定义类实现 Controller 接口,重写 handleRequest 方法。
  4. 自定义类实现 HttpRequestHandler 接口,重写 handleRequest 方法。

针对以上四种不同类型的处理器,需要调用不同的方法进行请求的处理:

  1. 执行 @RequestMapping(url) 修饰的方法。
  2. 调用 service() 方法。
  3. 强转为 Controller 类型,然后调用 handleRequest 方法。
  4. 强转为 HttpRequestHandler 类型,然后调用 handleRequest 方法。

所以提供了对应的适配器:

  1. RequestMappingHandlerAdapter:适配注解处理器
  2. SimpleServletHandlerAdapter:适配 Servlet 处理器
  3. SimpleControllerHandlerAdapter:适配 Controller 处理器
  4. HttpRerquestHandlerAdapter:适配 HttpRequestHandler 处理器

外部使用者遍历所有适配器,看当前是配置是否支持处理器,如果支持,则直接调用适配器的 handle 方法进行请求的处理。

当用户在浏览器地址栏输入一个请求后,会由 DispatcherServlet 的 service 方法进行处理,最终会调用到 doDispatch 方法:

org.springframework.web.servlet.DispatcherServlet#doDispatch

	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);// Determine handler for the current request.mappedHandler = getHandler(processedRequest);if (mappedHandler == null) {noHandlerFound(processedRequest, response);return;}// 获取处理器对应的适配器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;}// 执行适配器的 handle 方法mv = ha.handle(processedRequest, response, mappedHandler.getHandler());// 省略部分代码......

org.springframework.web.servlet.DispatcherServlet#getHandlerAdapter

	protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {if (this.handlerAdapters != null) {// 遍历所有适配器,找到支持该处理器的适配器for (HandlerAdapter adapter : this.handlerAdapters) {if (adapter.supports(handler)) {return adapter;}}}throw new ServletException("No adapter for handler [" + handler +"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");}

适配器 SimpleControllerHandlerAdapter 代码示例

// 适配 Controller 处理器
public class SimpleControllerHandlerAdapter implements HandlerAdapter {@Overridepublic boolean supports(Object handler) {	// 如果处理器是 Controller 类型,则支持该处理器return (handler instanceof Controller);}@Override@Nullablepublic ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {// 强转为 Controller,然后执行 handleRequest 方法return ((Controller) handler).handleRequest(request, response);}@Overridepublic long getLastModified(HttpServletRequest request, Object handler) {if (handler instanceof LastModified) {return ((LastModified) handler).getLastModified(request);}return -1L;}
}

本文链接:https://my.lmcjl.com/post/1340.html

展开阅读全文

4 评论

留下您的评论.