spring启动过程详解

AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext(MaxConfig.class);

这个ioc对象没有指定扫描路径,他是如何工作的呢?

这个构造方法如下:

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
   this();
   register(componentClasses);
   refresh();
}

可以看出这个构造方法,先使用了其他构造方法,其实就是完成扫描器和阅读器的初始化。

继续看就会发现是完成了注解的注册。

this.reader = new AnnotatedBeanDefinitionReader(this);

registerAnnotationConfigProcessors(registry, null);

最后在register(componentClasses);中使用上面的reader,注册就是把扫描到的class存在BeanDefinitionMap里面。

this.reader.register(componentClasses);

这里第一次执行完register,getBeanDefinitionMap里面只有这些,这里还没有扫描其他bean。

在这里插入图片描述

当执行到refresh();的时候,会调用doScan()进行扫描

从这个方法进,一步步到scan()方法。

invokeBeanFactoryPostProcessors(beanFactory);
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

112行

invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());

这个方法调用路径如下 :

org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors

上面方法继续调用postProcessor.postProcessBeanDefinitionRegistry(registry);这个方法,实现类如下org.springframework.context.annotation.ConfigurationClassPostProcessor

这个实现里面

processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);

org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions

这个方法的323行开始解析调用scan方法

// 解析每个 @Configuration
ConfigurationClassParser parser = new ConfigurationClassParser(
      this.metadataReaderFactory, this.problemReporter, this.environment,
      this.resourceLoader, this.componentScanBeanNameGenerator, registry);

这个parse调用170行的parse方法

org.springframework.context.annotation.ConfigurationClassParser#parse(java.util.Set<org.springframework.beans.factory.config.BeanDefinitionHolder>)

里面继续调用了parse方法

protected final void parse(@Nullable String className, String beanName) throws IOException {
   Assert.notNull(className, "No bean class name for configuration class bean definition");
   MetadataReader reader = this.metadataReaderFactory.getMetadataReader(className);
   processConfigurationClass(new ConfigurationClass(reader, beanName), DEFAULT_EXCLUSION_FILTER);
}

通过processConfigurationClass开始正式处理配置类。

do {
   sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
}
while (sourceClass != null);

进这个方法处理各种注解@PropertySource 、@ComponentScan、@Import 、@Bean等

Set<BeanDefinitionHolder> scannedBeanDefinitions =
      this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());

点进行看这里的parse方法,可以发现,这个方法的返回值便是doScan方法

这个方法里面,从传的参数componentScan里面找到basePackages,然后传入doScan方法,完成扫描。

在这里插入图片描述

String[] basePackagesArray = componentScan.getStringArray("basePackages");
return scanner.doScan(StringUtils.toStringArray(basePackages));

也就是在这里完成bean的扫描,整体流程如上所示。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring启动类的主方法通常长这样: ```java @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` 主方法中的`SpringApplication.run()`方法是Spring Boot的核心方法,用于启动Spring应用程序。该方法接受两个参数:启动类的.class和命令行参数args数组。 在执行`SpringApplication.run()`方法时,Spring会创建一个`SpringApplication`对象,并使用该对象来启动应用程序。在启动过程中,Spring会按照以下步骤进行: 1. 创建并配置一个`ApplicationContext`对象。 2. 执行所有的`BeanFactoryPostProcessor`对象,以便在ApplicationContext中注册所有Bean定义。 3. 执行所有的`BeanPostProcessor`对象,以便在Bean对象实例化之前或之后做一些自定义的处理。 4. 注册所有的`Bean`对象,并将它们注入到`ApplicationContext`中。 5. 执行所有的`ApplicationRunner`和`CommandLineRunner`对象,以便在应用程序启动后执行一些操作。 最后,`SpringApplication.run()`方法会返回一个`ApplicationContext`对象,可以使用它来获取和管理所有的Bean对象。 需要说明的是,Spring Boot框架提供了很多自动配置的功能,这些功能可以通过添加相应的依赖来启用。在启动类中,使用`@SpringBootApplication`注解来标注该类,它包含了多个注解,其中就包括`@EnableAutoConfiguration`注解,它会自动加载所有的自动配置类。因此,我们不需要手动配置很多东西,只需要添加相应的依赖即可。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值