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。还有,解读源码发现很多地方都使用到了工厂设计模式,作者修为浅薄,还不能说出所以然,这也是一个值得思考的问题,等我有了新的想法,会在本篇文章上继续分享。

  • 21
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值