Spring启动原理和可扩展设计分析
spring核心是一个容器,但是却能在它身上像插件一样集成很多功能,在设计上要做到封闭修改、扩展开放,这一点spring做的很优秀,对开发框架有很好的借鉴和指导意义。
本文通过分析spring的启动过程来分析spring扩展开放的设计实现,下面主要集中在两个点来分析:Aware和BeanPostProcessor。spring自身很多扩展功能也都是通过这两个机制来实现。
spring在启动过程中会注册很多回调来实现各种扩展功能,回调的形式最重要的是Aware和BeanPostProcessor。
spring各种不同业务都是一个思路:
每当spring容器完成某件事情(如ApplicationContext初始化完成)时都会通知Aware,Aware通常都具有一些setXXX()的方法,如BeanFactoryAware:
public interface BeanFactoryAware extends Aware { void setBeanFactory(BeanFactory beanFactory) throws BeansException; }
可以对spring扫描到的bean做手脚,初始化前和后
public interface BeanPostProcessor { Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException; Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException; }
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
实现Aware的各种bean接收到回调后就能获取各自想要的东西(ApplicationContext、ResourceLoader等),有了这些东西他们就可以实现自己的个性化逻辑
下面以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
这是上面说的典型的套路
实现了ServletContextAware的bean就这样获取到了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
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; }
接着上面的web原理
Dispatcher
Dispatcher是一个Servlet,是spring web的入口,来看下spring的dispatcher如何处理请求
spring mvc
Spring MVC的入口是Controller,那么解析Controller的东西自然就是SpringMVC的入口了。
这个入口就是:
RequestMappingHandlerMapping
这个东西继承了3个Aware
是不是很熟悉!
通过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); } }