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

适配器模式使得不兼容接口的对象能够协同工作。在Spring中,DisposableBeanAdapter用于统一销毁Bean的逻辑,处理各种销毁方法。DispatcherServlet通过HandlerAdapter适配器处理不同类型的处理器,如注解处理器、Servlet等。
摘要由CSDN通过智能技术生成

适配器模式

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

来源:https://refactoringguru.cn/design-patterns/adapter

适配器模式在 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

以下 spring 代码版本为 spring-framework-5.2.4

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

@Override
public void destroy() {
    // bean
    if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
       // 执行 @PreDestroy 注解指定的销毁方法
       for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
          processor.postProcessBeforeDestruction(this.bean, this.beanName);
       }
    }
    // 如果当前类实现了 DisposableBean
    if (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 方法:

以下 springmvc 代码版本为 spring-webmvc-5.2.7.RELEASE

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 {
	@Override
	public boolean supports(Object handler) {	
		// 如果处理器是 Controller 类型,则支持该处理器
		return (handler instanceof Controller);
	}
	@Override
	@Nullable
	public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		// 强转为 Controller,然后执行 handleRequest 方法
		return ((Controller) handler).handleRequest(request, response);
	}
	@Override
	public long getLastModified(HttpServletRequest request, Object handler) {
		if (handler instanceof LastModified) {
			return ((LastModified) handler).getLastModified(request);
		}
		return -1L;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悄悄地努力

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值