BeanFactory创建过程(基于Servlet)
- 1. 概述
- 1.2 那么问题就来了
- 1.2.1 谁负责AnnotationConfigServletWebServerApplicationContext实例呢?
- 1.2.2 ApplicationContextFactory初始化过程又是怎么样的?
- 1.3 总结
- 2. 最后
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 {@Overridepublic Class<? extends ConfigurableEnvironment> getEnvironmentType(WebApplicationType webApplicationType) {return (webApplicationType != WebApplicationType.REACTIVE) ? null : ApplicationReactiveWebEnvironment.class;}@Overridepublic ConfigurableEnvironment createEnvironment(WebApplicationType webApplicationType) {return (webApplicationType != WebApplicationType.REACTIVE) ? null : new ApplicationReactiveWebEnvironment();}@Overridepublic 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
现在清楚是什么情况了,那就把整个创建的过程走一下。
- 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;
}
- SpringApplication#createApplicationContext()
- 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
也就是AnnotationConfigServletWebServerApplicationContext
是DefaultApplicationContextFactory
的实现类去做的,而实例化DefaultApplicationContextFactory
是抛给了spring.factory
。
2. 最后
本篇幅多次提到DefaultListableBeanFactory
,下一章就研究研究BeanFactory
。还有,解读源码发现很多地方都使用到了工厂设计模式,作者修为浅薄,还不能说出所以然,这也是一个值得思考的问题,等我有了新的想法,会在本篇文章上继续分享。