spring boot原理分析(八):上下文Context即世界1

前言

    上下文Context可以说spring boot中最重要的一个概念,不仅包含了tomcat和spring mvc的启动和管理,还对spring mvc原有模式中的bean注册进行了大幅简化,理解Spring boot的Context可以说是理解spring boot的基础。
    原理分析(六)介绍了spring boot启动的主流程,run方法中最主要的部分即上下文的准备。

public ConfigurableApplicationContext run(String... args) {
    ......
    context = createApplicationContext();
    exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
        new Class[] { ConfigurableApplicationContext.class }, context);
    prepareContext(context, environment, listeners, applicationArguments, printedBanner);
    refreshContext(context);
    afterRefresh(context, applicationArguments);
    stopWatch.stop();
    ......
  return context;
}

上文代码中包括context的创建、准备、刷新和刷新后处理。刷新后处理的方法afterRefresh是模板方法,供子类继承填充代码逻辑。

上下文创建

protected ConfigurableApplicationContext createApplicationContext() {
  Class<?> contextClass = this.applicationContextClass;
  if (contextClass == null) {
    try {
      switch (this.webApplicationType) {
      case SERVLET:
        contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
        break;
      case REACTIVE:
        contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
        break;
      default:
        contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
      }
    }
    catch (ClassNotFoundException ex) {
      throw new IllegalStateException(
          "Unable create a default ApplicationContext, " + "please specify an ApplicationContextClass",
          ex);
    }
  }
  return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}

    上下文创建createApplicationContext还是会依据SERVLET、REACTIVE和NONE类型来创建相应的上下文。类型解释再引用一下原理分析(六)的内容。

SERVLET、REACTIVE和NONE。我们讲spring mvc是Servlet容器,所以服务即SERVLET WEB类型。REACTIVE也是一种WEB服务的类型,代表着非阻塞响应式编程,正是spirng mvc不擅长的事,具体可以参考spring-webflux。NONE类型说这个服务不是WEB类型,是其他服务类型。

Servlet服务对应的环境上下文是AnnotationConfigServletWebServerApplicationContext类,Reactive服务对应的环境上下文是AnnotationConfigReactiveWebServerApplicationContext类,而默认的上下文AnnotationConfigApplicationContext类。

上下文Context的定义

    根据ApplicationContext接口定义可以发现上下文的本质其实是一个“杂货铺”,继承的父类显示了上下文中包含的内容。

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
		MessageSource, ApplicationEventPublisher, ResourcePatternResolver {

	@Nullable
	String getId();

	String getApplicationName();

	String getDisplayName();

	long getStartupDate();

	@Nullable
	ApplicationContext getParent();

	AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;

}
  • 继承的父类接口EnvironmentCapable赋予了上下文获取应用程序的运行环境配置的能力。环境配置包括profile和properties配置,properties配置不仅包括项目内的properties文件,还有JVM system properties、操作系统环境变量等。
  • ListableBeanFactory和HierarchicalBeanFactory赋予了上下文获取bean、注册bean的能力。
  • MessageSource主要是国际化配置,比如语言等
  • ApplicationEventPublisher提供了上下文发送上下文状态改变事件的能力。这部分内容在原理分析(七)中有比较详细的介绍。
  • ResourcePatternResolver继承了ResourceLoader,是用来做资源的格式解析,比如各种配置文件等等。

这里需要注意的是,ApplicationContext接口中定义的都是getter类型的接口方法,没有setter类型的接口方法。这是因为不是所有上下文对象都提供修改内容的接口方法,只有ConfigurableApplicationContext接口的实现类提供了setter方法,可以修改上下文中的配置。这样做是为了防止上下文内容被随意变更。

上下文Context的实现
spring boot原理分析(八):上下文Context即世界1-AnnotationConfigServletWebServerApplicationContext.png     SERVLET上下文的最终实现是AnnotationConfigServletWebServerApplicationContext类,上图展示了这个类的继承结构。

    在ApplicationContext的更上层是基础层的接口,上面已经介绍了,这些接口打包构成了上下文的“杂货铺”。ApplicationContext下层是其不同类型的子接口或者子类,主要是根据功能或者应用对象对上下文进行了分类。
    WebApplicationContext接口添加了ServletContext getServletContext()方法。ServletContext的相关内容在spring mvc的原理(七)中,ServletConfig能够获取ServletContext的配置,其实代表就是spring mvc的应用本身。
    WebServerApplicationContext的接口里增加了WebServer getWebServer()的方法,这里具体代表的就是tomcat服务器本身。
    ConfigurableApplicationContext上面已经介绍过,是一个功能性的子接口,为ApplicationContext提供了setter的方法,所有有继承改接口的子类都拥有修改配置的能力。
    所以这样就很容易判断ConfigurableWebApplicationContext和ConfigurableWebServerApplicationContext具有的能力,实际上是功能分类和应用对象分类的一个拼合。
    接下来比较重要的是GenericApplicationContext,这个子类的特别之处在于继承了bean定义的注册BeanDefinitionRegistry。BeanDefinitionRegistry在原理分析(三)有过介绍,是用来用来注册bean的。GenericApplicationContext的使用方法的官方解释是,先使用BeanDefinitionRegistry注册一系列的bean,然后调用 AbstractApplicationContext.refresh()初始化这些bean。与普通ApplicationContext的实现类不同的是,GenericApplicationContext不会每次refresh创建一个新的BeanFactory实例,而是在构造时就会获取并持有一个BeanFactory实例,AbstractApplicationContext.refresh()可能只会被调用一次。
    使用以上子类或者子接口的功能进行拼合,就得出了GenericWebApplicationContext和ServletWebServerApplicationContext这两个类。
    最后对于AnnotationConfigServletWebServerApplicationContext,除了上述所有子接口和子类的功能之外,还实现了AnnotationConfigRegistry接口。AnnotationConfigRegistry这个接口主要是负责bean注解的注册和扫描工作,比如@Configuration注解。

    本文主要介绍了Spring boot的ApplicationContext的定义实现和创建,后续会对上下文的准备和刷新进行介绍。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值