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 {

@Override

public Class 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

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

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 getFromSpringFactories(WebApplicationType webApplicationType,

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

推荐文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: