<返回更多

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

2020-06-24    
加入收藏

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 >
<context-param>
 <param-name>contextConfigLocation</param-name>
 <param-value>classpath:conf/spring/applicationContext.xml</param-value>
</context-param>

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

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

web.mxl + DispatcherServlet

<servlet>
 <servlet-name>springMvc</servlet-name>
 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>

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如何处理请求

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

 

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<T, HandlerMethod> 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<HandlerInterceptor> interceptorList; */
 return getHandlerExecutionChain(handler, request);
 }
}
声明:本站部分内容来自互联网,如有版权侵犯或其他问题请与我们联系,我们将立即删除或处理。
▍相关推荐
更多资讯 >>>