SpringBoot 创建容器的实现

spring 容器的创建对应 SpringApplication 中 run 中调用的 createApplicationContext 方法。这里创建了一个 web 容器,接下就进去 prepareContext 容器准备阶段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
    SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
  //为容器设置环境
  context.setEnvironment(environment);
  //这里的空实现留给开发者扩展,设置数据转换的ConversionService
  postProcessApplicationContext(context);
  //执行容器中的 Initializers 的 initialize 方法
  applyInitializers(context);
  listeners.contextPrepared(context);
  if (this.logStartupInfo) {
    logStartupInfo(context.getParent() == null);
    logStartupProfileInfo(context);
  }
  // Add boot specific singleton beans
  ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
  beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
  if (printedBanner != null) {
    beanFactory.registerSingleton("springBootBanner", printedBanner);
  }
  if (beanFactory instanceof DefaultListableBeanFactory) {
    ((DefaultListableBeanFactory) beanFactory)
        .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
  }
  if (this.lazyInitialization) {
    context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
  }
  // Load the sources
  Set<Object> sources = getAllSources();
  Assert.notEmpty(sources, "Sources must not be empty");
  load(context, sources.toArray(new Object[0]));
  listeners.contextLoaded(context);
}
看一下这里的 load 方法,这里主要把我们的启动类作为 Bean 注册到了 Spring 的容器中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
protected void load(ApplicationContext context, Object[] sources) {
  if (logger.isDebugEnabled()) {
    logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
  }
  BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);
  if (this.beanNameGenerator != null) {
    loader.setBeanNameGenerator(this.beanNameGenerator);
  }
  if (this.resourceLoader != null) {
    loader.setResourceLoader(this.resourceLoader);
  }
  if (this.environment != null) {
    loader.setEnvironment(this.environment);
  }
  loader.load();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/**
 * Load the sources into the reader.
 * @return the number of loaded beans
 */
int load() {
  int count = 0;
  for (Object source : this.sources) {
    count += load(source);
  }
  return count;
}
 
private int load(Object source) {
  Assert.notNull(source, "Source must not be null");
  if (source instanceof Class<?>) {
    return load((Class<?>) source);
  }
  if (source instanceof Resource) {
    return load((Resource) source);
  }
  if (source instanceof Package) {
    return load((Package) source);
  }
  if (source instanceof CharSequence) {
    return load((CharSequence) source);
  }
  throw new IllegalArgumentException("Invalid source type " + source.getClass());
}
 
private int load(Class<?> source) {
  if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
    // Any GroovyLoaders added in beans{} DSL can contribute beans here
    GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class);
    load(loader);
  }
  if (isEligible(source)) {
    this.annotatedReader.register(source);
    return 1;
  }
  return 0;
}
再来看下 contextLoaded 方法,这里将上下文设置到监听器中,同时也把监听器添加到上下文中。最后发布了一个 ApplicationPreparedEvent 事件。

1
2
3
4
5
6
7
8
9
public void contextLoaded(ConfigurableApplicationContext context) {
  for (ApplicationListener<?> listener : this.application.getListeners()) {
    if (listener instanceof ApplicationContextAware) {
      ((ApplicationContextAware) listener).setApplicationContext(context);
    }
    context.addApplicationListener(listener);
  }
  this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context));
}
到此这篇关于SpringBoot 创建容器的实现的文章就介绍到这了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值