关于spring:SpringIoC源码分析一获取bean信息

好久没更新了,年末最初一个季度的确会比较忙,也是抽空看完了Spring的源码,这里进行一下回顾总结,当初Spring的源码切实太多,有的剖析的也很粗疏,这里就不打算剖析的太细了。还是依照之前的节奏,依照我看源码的几个点进行剖析。如果有什么问题,还心愿多多指教。上面开始源码剖析

Spring置信大家都用的最多的框架了,基本功能也都理解,这里就做过多介绍了(别问,问就是懒~)。咱们直切主题。反正我困惑的就几个点

  • IoC是怎么获取bean信息,并治理bean的
  • IoC引以为豪的依赖注入

    • IoC是怎么解决循环依赖的(没错齐全是因为网上说面试爱问)

    上面就针对这几个问题来看。

后期筹备

环境筹备

jdk:1.8

官网我的项目地址:https://github.com/spring-pro…

集体gitee地址:https://gitee.com/Nortyr/spri…

分支:self_note 原分支:5.2.x

测试代码

跟踪原始代码是通过传统的xml配置的形式,所以本篇以xml的形式为主,然而当初应该大多数都实用注解配置了,最初会解说下注解和xml的异同(就是扫描的形式不同)。

传统spring写法

public class Son {
   public void say(){
      System.out.println("say hello!");
   }
}
public class Father {
   private Son son;

   public void say(){
      son.say();
   }

   public void setSon(Son son) {
   }
}
public class Demo {
   public static void main(String[] args) {
      AbstractApplicationContext context = new ClassPathXmlApplicationContext("lifecycleTests2.xml",Demo.class);
      Father father=(Father) context.getBean("father");
      father.say();
   }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans-2.0.xsd">


   <bean id="son" class="org.springframework.test.self.xml2.Son" />
   <bean id="father" class="org.springframework.test.self.xml2.Father" >
      <property name="son" ref="son"/>
   </bean>

</beans>

注解版本

@Component
public class Son {

   public void say(){
      System.out.println("abcdefg");
   }
}
@Component
public class Father {
   @Autowired
   private Son son;

   public void say(){
      son.say();
      System.out.println("say hello");
   }
}
@ComponentScan("org.springframework.test.self.annotation")
public class Demo {
   public static void main(String[] args) {
      AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
      applicationContext.register(Demo.class);
      applicationContext.refresh();
      Father bean = (Father) applicationContext.getBean("father");
      bean.say();
   }
}

IoC如何获取Bean

依据mybatis的教训,必定就是到哪个中央解析xml,并生成对应的对象,而后依据配置,生成对应的类。spring解析也差不多这样

public ClassPathXmlApplicationContext(String[] paths, Class<?> clazz, @Nullable ApplicationContext parent)
      throws BeansException {

   super(parent);
   Assert.notNull(paths, "Path array must not be null");
   Assert.notNull(clazz, "Class argument must not be null");
   this.configResources = new Resource[paths.length];
   for (int i = 0; i < paths.length; i++) {
      this.configResources[i] = new ClassPathResource(paths[i], clazz);
   }
   //初始化容器
   refresh();
}

上面就进入到ioc外围,refresh()办法。

@Override
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      // Prepare this context for refreshing.
      //筹备此上下文以进行刷新,各种初始化配置
      prepareRefresh();

      // Tell the subclass to refresh the internal bean factory.
      //调用refreshBeanFactory(),通过createBeanFactory结构了一个ApplicationContext(DefaultApplicationContext)
      //同时启动了loadBeanDefinitions来载入BeanDefinition
      //通知子类刷新外部 bean 工厂。
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // Prepare the bean factory for use in this context.
      //筹备在此上下文中应用的beanFactory,配置零碎默认的一些bean
      prepareBeanFactory(beanFactory);

      try {
         // Allows post-processing of the bean factory in context subclasses.
         //设置BeanFactory的后置解决
         postProcessBeanFactory(beanFactory);

         // Invoke factory processors registered as beans in the context.
         //调用在上下文中注册为 beanFactory 的后置处理器。
         invokeBeanFactoryPostProcessors(beanFactory);

         // Register bean processors that intercept bean creation.
         //注册bean的后处理器,在bean创立的过程中调用
         registerBeanPostProcessors(beanFactory);

         // Initialize message source for this context.
         //初始化此上下文的音讯源
         initMessageSource();

         // Initialize event multicaster for this context.
         //为此上下文初始化事件机制
         initApplicationEventMulticaster();

         // Initialize other special beans in specific context subclasses.
         //初始化特定上下文子类中的其余非凡 bean。
         onRefresh();

         // Check for listener beans and register them.
         //查看侦听bean 并注册它们。
         registerListeners();

         // Instantiate all remaining (non-lazy-init) singletons.
         //实例化所有残余的(非提早初始化)单例。
         finishBeanFactoryInitialization(beanFactory);

         // Last step: publish corresponding event.
         //最初一步:公布相应的事件。
         finishRefresh();
      }

      catch (BeansException ex) {
         if (logger.isWarnEnabled()) {
            logger.warn("Exception encountered during context initialization - " +
                  "cancelling refresh attempt: " + ex);
         }

         // Destroy already created singletons to avoid dangling resources.|销毁曾经创立的单例以防止悬空资源。
         destroyBeans();

         // Reset 'active' flag.
         cancelRefresh(ex);

         // Propagate exception to caller.
         throw ex;
      }

      finally {
         // Reset common introspection caches in Spring's core, since we
         // might not ever need metadata for singleton beans anymore...
         //重置 Spring 外围中的常见内省缓存,因为咱们可能不再须要单例 bean 的元数据......
         resetCommonCaches();
      }
   }
}

本次解析的过程就是在这个办法中实现ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
   refreshBeanFactory();
   return getBeanFactory();
}

AbstractRefreshableApplicationContext#refreshBeanFactory外围就是这个办法,它创立了BeanFactory,BeanFactory就能够了解为IoC容器,封装了根本的办法。在各种ApplicationContext 例如ClassPathXmlApplicationContext,`
AnnotationConfigApplicationContext`中的具体实现也是通过BeanFactory

/**
 * This implementation performs an actual refresh of this context's underlying
 * bean factory, shutting down the previous bean factory (if any) and
 * initializing a fresh bean factory for the next phase of the context's lifecycle.
 * 此实现执行此上下文的底层 bean 工厂的理论刷新,敞开先前的 bean 工厂(如果有)并为上下文生命周期的下一个阶段初始化一个新的 bean 工厂。
 */
@Override
protected final void refreshBeanFactory() throws BeansException {
   if (hasBeanFactory()) {//如果有就销毁
      destroyBeans();
      closeBeanFactory();
   }
   try {
      //创立DefaultListableBeanFactory
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      beanFactory.setSerializationId(getId());
      customizeBeanFactory(beanFactory);
      //载入BeanDefinition信息,应用BeanDefinitionReader
      loadBeanDefinitions(beanFactory);
      this.beanFactory = beanFactory;
   }
   catch (IOException ex) {
      throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
   }
}

上面就进入bean的解析了,这里你就能够看到和MyBatis解析的差不多,创立一个对象,解析xml,最终后果都差不多,这里就不深刻了,喜爱的能够看后面的万字整顿MyBatis源码

@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
   // Create a new XmlBeanDefinitionReader for the given BeanFactory.|为给定的 BeanFactory 创立一个新的 XmlBeanDefinitionReader。
   XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

   // Configure the bean definition reader with this context's
   // resource loading environment.
   beanDefinitionReader.setEnvironment(this.getEnvironment());
   beanDefinitionReader.setResourceLoader(this);
   beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

   // Allow a subclass to provide custom initialization of the reader,
   // then proceed with actually loading the bean definitions.
   initBeanDefinitionReader(beanDefinitionReader);
   loadBeanDefinitions(beanDefinitionReader);
}

最初在XmlBeanDefinitionReader#doLoadBeanDefinitions中解析xml

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
      throws BeanDefinitionStoreException {

   try {
      Document doc = doLoadDocument(inputSource, resource);
      int count = registerBeanDefinitions(doc, resource);//对BeanDefinition解析的具体过程,这个解析会应用到Spring的Bean配置规定
      if (logger.isDebugEnabled()) {
         logger.debug("Loaded " + count + " bean definitions from " + resource);
      }
      return count;
   }
   ...catch略
}

接着就会解析各个节点,而后进入DefaultBeanDefinitionDocumentReader#processBeanDefinition进行解析

/** 解决给定的 bean 元素,解析 bean 定义并将其注册到注册表。
 * Process the given bean element, parsing the bean definition
 * and registering it with the registry.
 */
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
   //具体解决委托给BeanDefinitionParserDelegate实现
   //创立GenericBeanDefinition,设置属性,解析xml各个属性封装进BeanDefinitionHolder
   BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
   if (bdHolder != null) {
      //解析自定义标签
      bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
      try {
         // 注册解析失去的BeanDefinition
         BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
      }
      catch (BeanDefinitionStoreException ex) {
         getReaderContext().error("Failed to register bean definition with name '" +
               bdHolder.getBeanName() + "'", ele, ex);
      }
      // 在BeanDefinition向IOC容器注册实现当前,发送音讯
      getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
   }
}

这个BeanDefinitionHolder就是封装了BeanDefinition和bean名称与别名

public class BeanDefinitionHolder implements BeanMetadataElement {

   private final BeanDefinition beanDefinition;

   private final String beanName;

   @Nullable
   private final String[] aliases;
   //...其余略
}

BeanDefinition是个啥呢,能够看下接口规定的一些属性,这些属性基本上就是xml定义的bean标签的各种属性,相当于对应了每一个bean标签,解析过程如下(和mybatis很相似,略微看看就行了)


解析过程也如下所示(BeanDefinitionParserDelegate#parseBeanDefinitionElement(Element, 、String, BeanDefinition)

@Nullable
public AbstractBeanDefinition parseBeanDefinitionElement(
      Element ele, String beanName, @Nullable BeanDefinition containingBean) {

   this.parseState.push(new BeanEntry(beanName));

   String className = null;
   if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
      className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
   }
   String parent = null;
   if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
      parent = ele.getAttribute(PARENT_ATTRIBUTE);
   }

   try {
      AbstractBeanDefinition bd = createBeanDefinition(className, parent);
      //解析各个xml属性,并设置进beanDefinition
      parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
      bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

      parseMetaElements(ele, bd);
      parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
      parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

      parseConstructorArgElements(ele, bd);
      parsePropertyElements(ele, bd);
      parseQualifierElements(ele, bd);

      bd.setResource(this.readerContext.getResource());
      bd.setSource(extractSource(ele));

      return bd;
   }
  ...catch略过

   return null;
}

public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
      @Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {

   if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
      error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
   }
   else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
      bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
   }
   else if (containingBean != null) {
      // Take default from containing bean in case of an inner bean definition.
      bd.setScope(containingBean.getScope());
   }

   if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
      bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
   }

   String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
   if (isDefaultValue(lazyInit)) {
      lazyInit = this.defaults.getLazyInit();
   }
   bd.setLazyInit(TRUE_VALUE.equals(lazyInit));

   String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
   bd.setAutowireMode(getAutowireMode(autowire));

   if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
      String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
      bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
   }

   String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
   if (isDefaultValue(autowireCandidate)) {
      String candidatePattern = this.defaults.getAutowireCandidates();
      if (candidatePattern != null) {
         String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);
         bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
      }
   }
   else {
      bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));
   }

   ...ifelse 属性填充掠过

   return bd;
}

解析实现之后呢,就进入了

// 注册解析失去的BeanDefinition
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());

最初会在DefaultListableBeanFactory#registerBeanDefinition注册bean。也就是把Bean和BeanDefinition对应关系增加进`
DefaultListableBeanFactory::beanDefinitionMap,beanName增加进DefaultListableBeanFactory::beanDefinitionNames `
别名和beanName的对应关系增加进SimpleAliasRegistry::aliasMap

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
      throws BeanDefinitionStoreException {

   Assert.hasText(beanName, "Bean name must not be empty");
   Assert.notNull(beanDefinition, "BeanDefinition must not be null");

   if (beanDefinition instanceof AbstractBeanDefinition) {
      try {
         ((AbstractBeanDefinition) beanDefinition).validate();
      }
      catch (BeanDefinitionValidationException ex) {
         throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
               "Validation of bean definition failed", ex);
      }
   }
   //查看是否有同名的bean
   BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
   if (existingDefinition != null) {
      if (!isAllowBeanDefinitionOverriding()) {
         throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
      }
      else if (existingDefinition.getRole() < beanDefinition.getRole()) {
         // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
         if (logger.isInfoEnabled()) {
            logger.info("Overriding user-defined bean definition for bean '" + beanName +
                  "' with a framework-generated bean definition: replacing [" +
                  existingDefinition + "] with [" + beanDefinition + "]");
         }
      }
      else if (!beanDefinition.equals(existingDefinition)) {
         if (logger.isDebugEnabled()) {
            logger.debug("Overriding bean definition for bean '" + beanName +
                  "' with a different definition: replacing [" + existingDefinition +
                  "] with [" + beanDefinition + "]");
         }
      }
      else {
         if (logger.isTraceEnabled()) {
            logger.trace("Overriding bean definition for bean '" + beanName +
                  "' with an equivalent definition: replacing [" + existingDefinition +
                  "] with [" + beanDefinition + "]");
         }
      }
      this.beanDefinitionMap.put(beanName, beanDefinition);
   }
   else {
      if (hasBeanCreationStarted()) {
         // Cannot modify startup-time collection elements anymore (for stable iteration)
         synchronized (this.beanDefinitionMap) {
            this.beanDefinitionMap.put(beanName, beanDefinition);
            List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
            updatedDefinitions.addAll(this.beanDefinitionNames);
            updatedDefinitions.add(beanName);
            this.beanDefinitionNames = updatedDefinitions;
            removeManualSingletonName(beanName);
         }
      }
      else {//将bean增加进this.beanDefinitionMap,beanName增加进beanDefinitionNames
         // Still in startup registration phase|仍处于启动注册阶段
         this.beanDefinitionMap.put(beanName, beanDefinition);
         this.beanDefinitionNames.add(beanName);
         removeManualSingletonName(beanName);
      }
      this.frozenBeanDefinitionNames = null;
   }

   if (existingDefinition != null || containsSingleton(beanName)) {
      resetBeanDefinition(beanName);
   }
   else if (isConfigurationFrozen()) {
      clearByTypeCache();
   }
}

至此,bean解析就完了(解析过程还真是千篇一律)
上面咱们来看看bean解析的形式
在类上定义了@ComponentScan("org.springframework.test.self.annotation")那大略就是扫描包下的所有文件了

@ComponentScan("org.springframework.test.self.annotation")
public class Demo {
   public static void main(String[] args) {
      AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
      applicationContext.register(Demo.class);
      applicationContext.refresh();
      Father bean = (Father) applicationContext.getBean("father");
      bean.say();
   }
}

解析也不是在ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();中完了,而是在invokeBeanFactoryPostProcessors中实现

@Override
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
         ...略
         // Invoke factory processors registered as beans in the context.
         //调用在上下文中注册为 beanFactory 的后置处理器。
         invokeBeanFactoryPostProcessors(beanFactory);
         ...略
   }
}   

ConfigurationClassParser#doProcessConfigurationClass

@Nullable
protected final SourceClass doProcessConfigurationClass(
      ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
      throws IOException {

   if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
      // Recursively process any member (nested) classes first|首先递归解决任何成员(嵌套)类
      processMemberClasses(configClass, sourceClass, filter);
   }

   // Process any @PropertySource annotations
   for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
         sourceClass.getMetadata(), PropertySources.class,
         org.springframework.context.annotation.PropertySource.class)) {
      if (this.environment instanceof ConfigurableEnvironment) {
         processPropertySource(propertySource);
      }
      else {
         logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
               "]. Reason: Environment must implement ConfigurableEnvironment");
      }
   }

   // Process any @ComponentScan annotations
   Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
         sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
   if (!componentScans.isEmpty() &&
         !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
      for (AnnotationAttributes componentScan : componentScans) {
         // The config class is annotated with @ComponentScan -> perform the scan immediately配置类应用 @ComponentScan 注解 -> 立刻执行扫描,在这一步进行扫描
         Set<BeanDefinitionHolder> scannedBeanDefinitions =
               this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
         // Check the set of scanned definitions for any further config classes and parse recursively if needed
         for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
            BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
            if (bdCand == null) {
               bdCand = holder.getBeanDefinition();
            }
            if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
               parse(bdCand.getBeanClassName(), holder.getBeanName());
            }
         }
      }
   }

   // Process any @Import annotations
   processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

   // Process any @ImportResource annotations
   AnnotationAttributes importResource =
         AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
   if (importResource != null) {
      String[] resources = importResource.getStringArray("locations");
      Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
      for (String resource : resources) {
         String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
         configClass.addImportedResource(resolvedResource, readerClass);
      }
   }

   // Process individual @Bean methods
   Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
   for (MethodMetadata methodMetadata : beanMethods) {
      configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
   }

   // Process default methods on interfaces
   processInterfaces(configClass, sourceClass);

   // Process superclass, if any
   if (sourceClass.getMetadata().hasSuperClass()) {
      String superclass = sourceClass.getMetadata().getSuperClassName();
      if (superclass != null && !superclass.startsWith("java") &&
            !this.knownSuperclasses.containsKey(superclass)) {
         this.knownSuperclasses.put(superclass, configClass);
         // Superclass found, return its annotation metadata and recurse
         return sourceClass.getSuperClass();
      }
   }

   // No superclass -> processing is complete
   return null;
}

而后就是层层解析,找到合乎的class文件

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
   Set<BeanDefinition> candidates = new LinkedHashSet<>();
   try {
      String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
            resolveBasePackage(basePackage) + '/' + this.resourcePattern;
      //TODO 重要注解扫描某个包下的所有文件
      Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
      boolean traceEnabled = logger.isTraceEnabled();
      boolean debugEnabled = logger.isDebugEnabled();
      for (Resource resource : resources) {
         if (traceEnabled) {
            logger.trace("Scanning " + resource);
         }
         try {
            MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
            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 (FileNotFoundException ex) {
            if (traceEnabled) {
               logger.trace("Ignored non-readable " + resource + ": " + ex.getMessage());
            }
         }
         catch (Throwable ex) {
            throw new BeanDefinitionStoreException(
                  "Failed to read candidate component class: " + resource, ex);
         }
      }
   }
   catch (IOException ex) {
      throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
   }
   return candidates;
}

生成ScannedGenericBeanDefinition


前面就差不多一样了,把Bean和BeanDefinition对应关系增加进`
DefaultListableBeanFactory::beanDefinitionMap,beanName增加进DefaultListableBeanFactory::beanDefinitionNames `

总结

总结一下spring解析的大体流程:

  • 寻找:

    • xml:解析配置,生成对应的对象。
    • 注解,找到后期注册进上下文中的类,循环找到对应的@ComponentScan注解找到包下的所有类
  • bean解析:获取到对应的配置信息,封装进BeanDefinition,(xml:GenericBeanDefinition,注解:ScannedGenericBeanDefinition)
  • 注册:

    • Bean和BeanDefinition对应关系增加进DefaultListableBeanFactory::beanDefinitionMap
    • beanName增加进DefaultListableBeanFactory::beanDefinitionNames

【腾讯云】云产品限时秒杀,爆款1核2G云服务器,首年50元

阿里云限时活动-2核2G-5M带宽-60G SSD-1000G月流量 ,特惠价99元/年(原价1234.2元/年,可以直接买3年),速抢

本文由乐趣区整理发布,转载请注明出处,谢谢。

您可能还喜欢...

发表评论

您的电子邮箱地址不会被公开。

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据