Spring启动原理和可扩展设计分析
简述spring核心是一个容器 , 但是却能在它身上像插件一样集成很多功能 , 在设计上要做到封闭修改、扩展开放 , 这一点spring做的很优秀 , 对开发框架有很好的借鉴和指导意义 。
本文通过分析spring的启动过程来分析spring扩展开放的设计实现 , 下面主要集中在两个点来分析:Aware和BeanPostProcessor 。spring自身很多扩展功能也都是通过这两个机制来实现 。
原则spring在启动过程中会注册很多回调来实现各种扩展功能 , 回调的形式最重要的是Aware和BeanPostProcessor 。
spring各种不同业务都是一个思路:
- 创建不同的ApplicationContext
- 不同的ApplicationContext写死一个Aware类型的BeanPostProcessor
- 由写死的Aware类型BeanPostProcessor来加载特殊业务的各种逻辑
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
- ApplicationContextAware
- ApplicationEventPublisherAware
- ResourceLoaderAware
- EmbeddedValueResolverAware
- 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
- ServletContextAware
- 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
推荐阅读
- Redis哨兵原理,我忍你很久了
- 今日头条算法原理—— 3分钟了解今日头条推荐算法原理
- 建议收藏学习 一篇文章弄懂SpringBoot中WebMvcConfigurer
- 核武器原理都知道,为何很多国家倾全力也造不出,究竟难在哪里?
- 深入理解Go的interface内部执行原理
- 一 基本Spring Cloud的微服务架构搭建及应用
- 使用“全新启动”功能重置电脑,还原一个纯净原版的win10系统
- 普洱熟茶饼和生茶,普洱生茶和普洱熟茶减肥原理不同
- 用elastic-job-lite玩转SpringBoot定时器管理
- 如何在重启或启动时执行命令或脚本