Spring启动原理和可扩展设计分析

简述

spring核心是一个容器,但是却能在它身上像插件一样集成很多功能,在设计上要做到封闭修改、扩展开放,这一点spring做的很优秀,对开发框架有很好的借鉴和指导意义。

本文通过分析spring的启动过程来分析spring扩展开放的设计实现,下面主要集中在两个点来分析:Aware和BeanPostProcessor。spring自身很多扩展功能也都是通过这两个机制来实现。

原则

spring在启动过程中会注册很多回调来实现各种扩展功能,回调的形式最重要的是Aware和BeanPostProcessor。

spring各种不同业务都是一个思路:

  1. 创建不同的ApplicationContext
  2. 不同的ApplicationContext写死一个Aware类型的BeanPostProcessor
  3. 由写死的Aware类型BeanPostProcessor来加载特殊业务的各种逻辑

Aware

每当spring容器完成某件事情(如ApplicationContext初始化完成)时都会通知Aware,Aware通常都具有一些setXXX()的方法,如BeanFactoryAware:

public interface BeanFactoryAware extends Aware { void setBeanFactory(BeanFactory beanFactory) throws BeansException;}

BeanPostProcessor

可以对spring扫描到的bean做手脚,初始化前和后

public interface BeanPostProcessor { Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException; Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;}

Spring 启动过程

spring容器启动的模板编排在org.springframework.context.support.AbstractApplicationContext#refresh

public void refresh() throws BeansException, IllegalStateException { prepareRefresh(); // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. //子类通常在这里添加自己需要的BeanPostProcessor postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. //查找所有BeanPostProcessor并注册到容器中,bean初始化时会来调用bpp registerBeanPostProcessors(beanFactory); // Initialize message source for this context. initMessageSource(); // Initialize event multicaster for this context. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // Check for listener beans and register them. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); }}

其中AbstractApplicationContext#prepareBeanFactory里注册ApplicationContext的Aware处理器:

beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this))

ApplicationContextAwareProcessor里会触发各种aware

  1. ApplicationContextAware
  2. ApplicationEventPublisherAware
  3. ResourceLoaderAware
  4. EmbeddedValueResolverAware
  5. EnvironmentAware

实现Aware的各种bean接收到回调后就能获取各自想要的东西(ApplicationContext、ResourceLoader等),有了这些东西他们就可以实现自己的个性化逻辑

spring web启动

下面以spring web为例看看Spring web是如何在spring的基础上实现扩展的。

spring web的ApplicationContext大多集成自AbstractRefreshableWebApplicationContext

首先,还是那个套路,创建特殊的ApplicationContext,然后写死一个BeanPostProcessor

AbstractRefreshableWebApplicationContext#postProcessBeanFactory

@Override protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));  }

ServletContextAwareProcessor处理两种类型的Aware

  1. ServletContextAware
  2. ServletConfigAware

这是上面说的典型的套路

实现了ServletContextAware的bean就这样获取到了web上下文,可以做自己的事情了

spring web初始化方式

web.xml + ContextLoaderListener

< listener > < listener-class > org.springframework.web.context.ContextLoaderListener  listener-class > listener >contextConfigLocationclasspath:conf/spring/applicationContext.xml

ContextLoaderListener 初始化WebApplicationContext 判断启动哪种WebApplicationContext

  1. web.xml 里的context-param找contextClass
  2. 没有的话就加载默认:spring jar里ContextLoader.properties写的XmlWebApplicationContext

web.mxl + DispatcherServlet

springMvcorg.springframework.web.servlet.DispatcherServlet

DispatcherServlet基于Servlet生命周期会在javax.servlet.GenericServlet.init()初始化spring容器

springboot

DispatcherServletAutoConfiguration

@Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME) public DispatcherServlet dispatcherServlet() { DispatcherServlet dispatcherServlet = new DispatcherServlet(); dispatcherServlet.setDispatchOptionsRequest( this.webMvcProperties.isDispatchOptionsRequest()); dispatcherServlet.setDispatchTraceRequest( this.webMvcProperties.isDispatchTraceRequest()); dispatcherServlet.setThrowExceptionIfNoHandlerFound( this.webMvcProperties.isThrowExceptionIfNoHandlerFound()); return dispatcherServlet; }

Spring MVC原理

接着上面的web原理

Dispatcher

Dispatcher是一个Servlet,是spring web的入口,来看下spring的dispatcher如何处理请求




springframework 启动类 spring启动机制_xml


spring mvc

Spring MVC的入口是Controller,那么解析Controller的东西自然就是SpringMVC的入口了。

这个入口就是:

RequestMappingHandlerMapping

这个东西继承了3个Aware

  1. ApplicationAware(Spring web)
  2. ServletContextAware (Spring web)
  3. EmbeddedValueResolverAware (Spring context)

是不是很熟悉!

通过Aware,Spring mvc就这么起来了!并且能够自定义解析各种注解

RequestMappingHandlerMapping

内部维护一个Map handlerMethods,T就是Controller的类

public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping implements MatchableHandlerMapping, EmbeddedValueResolverAware { /** 1. 初始化 */ public void afterPropertiesSet() { initHandlerMethods(); } /** 2. 扫描所有Object的bean,扫描Controller、RequestMapping 3. 扫描每个controller的web请求方法,写入到handlerMethods里,以后处理请求时用来对应查找 */  protected void initHandlerMethods() {  String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ? BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) : getApplicationContext().getBeanNamesForType(Object.class)); for (String beanName : beanNames) { if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX) && isHandler(getApplicationContext().getType(beanName))){ //查找web请求方法 detectHandlerMethods(beanName); } } handlerMethodsInitialized(getHandlerMethods()); } @Override protected boolean isHandler(Class> beanType) { return ((AnnotationUtils.findAnnotation(beanType, Controller.class) != null) || (AnnotationUtils.findAnnotation(beanType, RequestMapping.class) != null)); } /** 4. 处理web请求时负责找到对应的处理方法 */ @Override public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { Object handler = getHandlerInternal(request); if (handler == null) { handler = getDefaultHandler(); } if (handler == null) { return null; } // Bean name or resolved handler? if (handler instanceof String) { String handlerName = (String) handler; handler = getApplicationContext().getBean(handlerName); } /** 组装HandlerExecutionChain,里面主要包括处理列表: List interceptorList; */ return getHandlerExecutionChain(handler, request); }}