BeanFactory创建过程(基于Servlet)

1. 概述

AnnotationConfigServletWebServerApplicationContext的类图。
在这里插入图片描述

GenericApplicationContext类有一个构造函数,直接实例化了DefaultListableBeanFactory,它就是BeanFactory

public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
   

    /**
     * Create a new GenericApplicationContext.
     * @see #registerBeanDefinition
     * @see #refresh
    */
    public GenericApplicationContext() {
   
        this.beanFactory = new DefaultListableBeanFactory();
    }
}

从上面的类图可以看到AnnotationConfigServletWebServerApplicationContext间接的继承了GenericApplicationContext,因为类的继承规则,所以只要创建AnnotationConfigServletWebServerApplicationContext对象,GenericApplicationContext也会被实例化,自然的DefaultListableBeanFactory也会被实例化。

1.2 那么问题就来了

1.2.1 谁负责AnnotationConfigServletWebServerApplicationContext实例呢?

在这里插入图片描述

有一个ApplicationContextFactory工厂类,从上图可以发现它有3个实现类,我们主要看基于注解的实现类AnnotationConfigServletWebServerApplicationContext。可以从下面的实现代码发现,create调用了AnnotationConfigReactiveWebServerApplicationContext无参的构造函数。这个时候问题又来了,ApplicationContextFactory又是怎么初始化的?

static class Factory implements ApplicationContextFactory {
   

    @Override
    public Class<? extends ConfigurableEnvironment> getEnvironmentType(WebApplicationType webApplicationType) {
   
        return (webApplicationType != WebApplicationType.REACTIVE) ? null : ApplicationReactiveWebEnvironment.class;
    }

    @Override
    public ConfigurableEnvironment createEnvironment(WebApplicationType webApplicationType) {
   
        return (webApplicationType != WebApplicationType.REACTIVE) ? null : new ApplicationReactiveWebEnvironment();
    }

    @Override
    public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
   
        return (webApplicationType != WebApplicationType.REACTIVE) ? null
            : new AnnotationConfigReactiveWebServerApplicationContext();
    }

}

1.2.2 ApplicationContextFactory初始化过程又是怎么样的?

在这里插入图片描述

spring-boot-2.7.16的jar包中可以发现spring.factories中有下面两行代码,可以使用SpringFactoriesLoader.loadFactories(ApplicationContextFactory.class, getClass().getClassLoader()) 去获取到下面两个对象。

# Application Context Factories
org.springframework.boot.ApplicationContextFactory=\
org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext.Factory,\
org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext.Factory

现在清楚是什么情况了,那就把整个创建的过程走一下。

  1. SpringApplication#run(String…args)
    下面创建的BeanFactory其实就是ConfigurableApplicationContext,其实在ApplicationContextFactory中创建的是AnnotationConfigServletWebServerApplicationContext,从概述的类图中可以看到AnnotationConfigServletWebServerApplicationContext间接的继承了ConfigurableApplicationContext
public ConfigurableApplicationContext run(String... args) {
   
    long startTime = System.nanoTime();
    DefaultBootstrapContext bootstrapContext = createBootstrapContext();
    ConfigurableApplicationContext context = null;
    configureHeadlessProperty();
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.starting(bootstrapContext, this.mainApplicationClass);
    try {
   
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
        configureIgnoreBeanInfo(environment);
        Banner printedBanner = printBanner(environment);
        // 这里就是创建BeanFactory的方法
        context = createApplicationContext();
        context.setApplicationStartup(this.applicationStartup);
        prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
        refreshContext(context);
        afterRefresh(context, applicationArguments);
        Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
        if (this.logStartupInfo) {
   
            new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
        }
        listeners.started(context, timeTakenToStartup);
        callRunners(context, applicationArguments);
    }
    catch (Throwable ex) {
   
        handleRunFailure(context, ex, listeners);
    throw new IllegalStateException(ex);
    }
    try {
   
        Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
        listeners.ready(context, timeTakenToReady);
    }
    catch (Throwable ex) {
   
        handleRunFailure(context, ex, null);
        throw new IllegalStateException(ex);
    }
    return context;
}
  1. SpringApplication#createApplicationContext()
  2. DefaultApplicationContextFactory#create() & getFromSpringFactories()
    SpringApplication#createApplicationContext()方法最终调用了DefaultApplicationContextFactory类的create方法,又调用getFromSpringFactories方法,这个方法就是从spring.factory文件找ApplicationContextFactory的实现类。
public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
   
    try {
   
        return getFromSpringFactories(webApplicationType, ApplicationContextFactory::create,
            AnnotationConfigApplicationContext::new);
    }
    catch (Exception ex) {
   
        throw new IllegalStateException("Unable create a default ApplicationContext instance, "
            + "you may need a custom ApplicationContextFactory", ex);
    }
}
// 从spring.factory中获取ApplicationContextFactory的实现类
private <T> T getFromSpringFactories(WebApplicationType webApplicationType,
    BiFunction<ApplicationContextFactory, WebApplicationType, T> action, Supplier<T> defaultResult) {
   
    for (ApplicationContextFactory candidate : SpringFactoriesLoader.loadFactories(ApplicationContextFactory.class,
        getClass().getClassLoader())) {
   
        // Java8 的写法这里的action就是ApplicationContextFactory的create方法
        // 可以理解为ApplicationContextFactory::create
        // 也可以理解为ApplicationContextFactory.create()
        T result = action.apply(candidate, webApplicationType);
        if (result != null) {
   
            return result;
        }
    }
    return (defaultResult != null) ? defaultResult.get() : null;
}

1.3 总结

这里来一个小总结,方便记忆。下面是整个过程:

SpringApplication#run -> SpringApplication#createAppliction -> DefaultApplicationContextFactory#create -> DefaultApplicationContextFactory#getFromSpringFactory -> SpringFactoriesLoader#loadFactories

可以知道实例化BeanFactory也就是AnnotationConfigServletWebServerApplicationContextDefaultApplicationContextFactory的实现类去做的,而实例化DefaultApplicationContextFactory是抛给了spring.factory

2. 最后

本篇幅多次提到DefaultListableBeanFactory,下一章就研究研究BeanFactory。还有,解读源码发现很多地方都使用到了工厂设计模式,作者修为浅薄,还不能说出所以然,这也是一个值得思考的问题,等我有了新的想法,会在本篇文章上继续分享。

相关推荐

  1. Servlet基础之配置 Servlet 及其映射

    2024-02-01 16:16:03       58 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-02-01 16:16:03       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-02-01 16:16:03       101 阅读
  3. 在Django里面运行非项目文件

    2024-02-01 16:16:03       82 阅读
  4. Python语言-面向对象

    2024-02-01 16:16:03       91 阅读

热门阅读

  1. 快速掌握WebSocket:仅需10分钟的速成教程!

    2024-02-01 16:16:03       52 阅读
  2. Prometheus监控告警

    2024-02-01 16:16:03       39 阅读
  3. c++指针解释

    2024-02-01 16:16:03       57 阅读
  4. ubuntu系统中,什么情况会发生内存交换(Swap)

    2024-02-01 16:16:03       48 阅读
  5. 运算符重载需要注意的事项:

    2024-02-01 16:16:03       52 阅读
  6. SQL中LIMIT的简单用法

    2024-02-01 16:16:03       50 阅读
  7. OpenVoice文本转语音大模型实战部署

    2024-02-01 16:16:03       44 阅读