Bean的生命周期

本文围绕Spring中Bean的生命周期展开,介绍了扫描生成BeanDefinition的过程,包括ConfigurationClassPostProcessor类解析配置类和ClassPathBeanDefinitionScanner类的扫描逻辑。还阐述了从实例化到销毁Bean的完整生命周期,以及各阶段Bean后置处理器的执行顺序,帮助理解Spring框架中Bean的管理机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Bean的生命周期,就是从创建Bean到销毁Bean的过程。在这个过程中,Spring提供了很多扩展点,这些扩展点具象化的表示就是各种BeanPostProcessor(Bean的后置处理器)的实现。本篇主要的内容就是介绍扫描Bean、实例化Bean、销毁Bean以及中间夹杂着执行各种Bean的后置处理器的过程。

下面的流程图包括了Bean的整个生命周期,对于ApplicationContext容器,所有的非懒加载的单例Bean都是在容器启动时创建的,因此Bean的整个生命周期的绝大多数过程都是在容器启动时发生的。容器启动时首先创建并初始化BeanFactory,随后执行一些特定的BeanFactoryPostProcessor(BeanFactory后置处理器)方法,其中就包括执行扫描包路径逻辑的ConfigurationClassPostProcessor类,今天的介绍也从该类开始。

扫描生成BeanDefinition

ConfigurationClassPostProcessor类最主要的功能是解析配置类,扫描过程是在其解析配置类上的@ComponentScan注解后进行的,关于容器启动和解析配置类在其他部分已经详细介绍过,此处不再赘述。最终执行扫描逻辑的是ClassPathBeanDefinitionScanner类的doScan()方法。

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
   Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
    //遍历扫描从@ComponentScan注解得到的所有包路径
   for (String basePackage : basePackages) {
		//findCandidateComponents()方法执行扫描逻辑并将扫描到的Bean解析生成BeanDefinition
      Set<BeanDefinition> candidates = findCandidateComponents(basePackage);

      for (BeanDefinition candidate : candidates) {
         ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
         candidate.setScope(scopeMetadata.getScopeName());

         String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);

         if (candidate instanceof AbstractBeanDefinition) {
            postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
         }
         if (candidate instanceof AnnotatedBeanDefinition) {
            // 解析@Lazy、@Primary、@DependsOn、@Role、@Description
       AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
         }

         // 检查Spring容器中是否已经存在该beanName
         if (checkCandidate(beanName, candidate)) {
            BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
            definitionHolder =
                  AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
            beanDefinitions.add(definitionHolder);

            // 将生成的BeanDefinition注册到BeanFactory
            registerBeanDefinition(definitionHolder, this.registry);
         }
      }
   }
   return beanDefinitions;
}

doScan()方法主要是扫描从配置类上的@ComponentScan注解得到的所有包路径,将得到的Bean生成BeanDefinition,最后将其注册到BeanFactory中以便于后面随时对Bean进行实例化。此方法中的核心方法是findCandidateComponents()方法。

public Set<BeanDefinition> findCandidateComponents(String basePackage) {
   if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
      return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
   }
   else {
      return scanCandidateComponents(basePackage);
   }
}

在findCandidateComponents()中,一般情况下进入的是scanCandidateComponents()方法。

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
   Set<BeanDefinition> candidates = new LinkedHashSet<>();
   try {
      // 获取basePackage下所有的文件资源
      String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
            resolveBasePackage(basePackage) + '/' + this.resourcePattern;
      Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
      boolean traceEnabled = logger.isTraceEnabled();
      boolean debugEnabled = logger.isDebugEnabled();
      for (Resource resource : resources) {
         if (traceEnabled) {
            logger.trace("Scanning " + resource);
         }
         if (resource.isReadable()) {
            try {
                //1.通过元数据读取器读取资源文件的元数据
               MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
               // 2.根据excludeFilters、includeFilters判断BeanDefinition是否是Bean
               if (isCandidateComponent(metadataReader)) { 
                  ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                  sbd.setSource(resource);

                  if (isCandidateComponent(sbd)) {
                     if (debugEnabled) {
                        logger.debug("Identified candidate component class: " + resource);
                     }
                     candidates.add(sbd);
                  }
                  else {
                     if (debugEnabled) {
                        logger.debug("Ignored because not a concrete top-level class: " + resource);
                     }
                  }
               }
               else {
                  if (traceEnabled) {
                     logger.trace("Ignored because not matching any filter: " + resource);
                  }
               }
            }
            catch (Throwable ex) {
               throw new BeanDefinitionStoreException(
                     "Failed to read candidate component class: " + resource, ex);
            }
         }
         else {
            if (traceEnabled) {
               logger.trace("Ignored because not readable: " + resource);
            }
         }
      }
   }
   catch (IOException ex) {
      throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
   }
   return candidates;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值