SpringBoot 应用使用自定义的 ApplicationContext 实现类
欢迎访问我的 GitHub
这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos
为什么要自定义 application context
在学习 spring 容器初始化的过程中,发现 spring 容器预留了一些扩展点,我们可以写子类来做功能扩展,例如 AbstractApplicationContext 类的 initPropertySources、postProcessBeanFactory、onRefresh 等方法都是空方法,留给子类来扩展用;
在传统 spring 框架下的扩展方式
传统的 spring 框架下使用哪个 ApplicationContext 实现类,是自己写代码来指定的,下面是基于 spring 框架的应用的启动代码:
如果我们要用自定的 ApplicationContext 实现类,只要将上面的 ClassPathXmlApplicationContext 改成我们做的类即可;
探寻 SpringBoot 框架下的扩展方式
先看一段代码,以下是一个 SpringBoot 应用启动的代码:
从上述代码可知,我们需要去查看 SpingApplication 的 run 方法源码,那里应该有 ApplicationContext 初始化相关的信息,在 SpingApplication 的 run 方法中,果然找到了有用信息,如下图红框所示,是 createApplicationContext 方法创建了 ApplicationContext 实现类:
去看看 createApplicationContext 方法,如下图:
上图中有两点需要注意:
红框中显示,ApplicationContext 实现类来自成员变量 applicationContextClass,只要我们能设置成员变量 applicationContextClass,就达到了目的:在应用中使用自定义的 ApplicationContext 实现类;
绿框中显示,如果没有设置成员变量 applicationContextClass,就把 AnnotationConfigServletWebServerApplicationContext 作为 ApplicationContext 实现类,用在 spring 环境中,所以,我们在自定义 ApplicationContext 实现类时,用 AnnotationConfigServletWebServerApplicationContext 作为父类最合适(除了我们自己扩展的东西,其他部分都和默认的保持一致);
如何设置自定义的 ApplicationContext 实现类
从 createApplicationContext 方法可以看出,设置了成员变量 applicationContextClass,就达到了使用自定义 ApplicationContext 实现类的目的,那么如何设置成员变量 applicationContextClass 呢?就在下面这个 setApplicationContextClass 方法:
我们只要在启动应用的时候,在调用 springApplication 的 run 方法之前先调用 setApplicationContextClass 方法就能指定 ApplicationContext 实现类了;
分析到此,您是否和我一样有疑虑:setApplicationContextClass 方法会不会被在其他地方被调用,导致我们的设置无效呢?通过以下两种方法来检查:
在 IntelliJ IDEA 中,通过"Find Usages"的方式查找该方法被调用的地方,结果只发现了一处 SpringBootServletInitializer 类的 onStartup 方法,这是 war 包形式的应用在配置 Initializer 的时候才会用到,main 方法启动的方式中不会用到;
在 setApplicationContextClass 方法中打断点,debug 启动应用,确认不会走进来;
实战使用自定义的 ApplicationContext 实现类
理论分析完毕,可以实战验证了:
基于 maven 创建一个 SpringBoot 的 web 应用,pom.xml 如下:
创建类 CustomizeApplicationContext,继承自 AnnotationConfigServletWebServerApplicationContext,重写了父类的几个方法,如下:
启动类 CustomizeapplicationcontextApplication 的 main 方法中,调用 setApplicationContextClass 方法,将 ApplicationContext 实现类设置为 CustomizeApplicationContext:
启动应用,查看日志如下,CustomizeApplicationContext 中重写的方法都被执行了,并且 initPropertySources 被执行了两次,那是因为除了 AbstractApplicationContext 类中有调用,在 ServletWebServerApplicationContext 类的 onRefresh 中会执行 createWebServer 方法,而 createWebServer 方法中也会调用一次 initPropertySources 方法:
实战源码下载
本章实战的源码可以在 github 下载,地址和链接信息如下表所示:
这个 git 项目中有多个文件夹,本章源码在文件夹 customizeapplicationcontext 下,如下图红框所示:
至此,我们通过查看 SpringApplication 的源码,搞清楚了 spring 环境的 ApplicationContext 实现类在 SpringBoot 框架下如何指定,也做了一次简单的自定义实战,今后在研究和学习 spring 过程中,如果需要扩展 spring 容器就能在 SpringBoot 环境下进行了,相比传统的 war 包部署、以及指定多个 jar 包的 classpath 等操作,springboot 应用的单个 jar 包更方便省事。
欢迎关注 InfoQ:程序员欣宸
版权声明: 本文为 InfoQ 作者【程序员欣宸】的原创文章。
原文链接:【http://xie.infoq.cn/article/c29c21e953ff70a9e8f69aa0e】。文章转载请联系作者。
评论