Spring源码解析二 (IOC容器初始化方式一:XmlBeanFactory)

目录

1. 配置资源加载

2. 配置资源解析以及根节点的获取

3. 注册BeanDefinition

3.1 默认命名空间解析

3.1.1 标签处理解析

3.1.2 BeanDefinition的注册

3.2 自定义命名空间解析

3.2.1 获取名称处理器

3.2.2 根据标签名称获取解析器

3.2.3 解析自定义标签


使用示例(已过时):

XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("bean.xml"));
UserService userService2 = (UserService) bf.getBean("xxx");
userService2.query();

分析:

  1. 通过XmlBeanFactory的构造方法,创建XmlBeanFactory实例
  2. 通过XmlBeanFactory实例的getBean()方法获取执行bean实例
  3. 调用目标bean的方法

XmlBeanFactory#XmlBeanFactory实现:

public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
   super(parentBeanFactory);
   this.reader.loadBeanDefinitions(resource);
}

分析:

  1.  调用父构造函数, 在AbstractAutowireCapableBeanFactory类的构造函数中设置忽略给定接口的自动装配功能, 并调用AbstractBeanFactory类中的setParentBeanFactory()方法设置双亲IoC容器
  2. 加载bean, 该方法返回int类型数值表示注册bean定义的数量

1. 配置资源加载

XmlBeanDefinitionReader#loadBeanDefinitions实现:

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
   //1.非空判断及日志记录
   ...
   //2.通过set集合来记录当前正在加载的资源
   Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
   if (currentResources == null) {
      currentResources = new HashSet<>(4);
      this.resourcesCurrentlyBeingLoaded.set(currentResources);
   }
   //将encodedResource添加到currentResources集合中,如果添加失败,则抛出异常
   if (!currentResources.add(encodedResource)) {
      throw new BeanDefinitionStoreException(
            "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
   }
   //3.加载bean
   try {
      //通过encodedResource获取已经封装的Resource对象并再次从Resource中获取其中的inputStream
      InputStream inputStream = encodedResource.getResource().getInputStream();
      try {
         //org.xml.sax.InputSource
         InputSource inputSource = new InputSource(inputStream);
         //如果encodedResource中设置的编码不为空,则设置inputSource的编码
         if (encodedResource.getEncoding() != null) {
            inputSource.setEncoding(encodedResource.getEncoding());
         }
         /**
          * 加载bean,核心部分
          */
         return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
      }
      finally {
         //关闭输入流
         inputStream.close();
      }
   }
   ...
   finally {
      //加载完毕,将encodedResource从currentResources集合中移除
      currentResources.remove(encodedResource);
      if (currentResources.isEmpty()) {
         this.resourcesCurrentlyBeingLoaded.remove();
      }
   }
}

分析:

  1. 非空判断及日志记录
  2. 通过currentResources集合来记录当前正在加载的资源
  3. 对资源信息进行封装并准备加载bean
  4. 加载完毕,将encodedResource从currentResources集合中移除

XmlBeanDefinitionReader#doLoadBeanDefinitions实现:

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
      throws BeanDefinitionStoreException {
   try {
      /**
       * 将配置文件解析为一个Document实例,以便下面对Bean定义进行解析
       */
      Document doc = doLoadDocument(inputSource, resource);
      /**
       * 上一个方法中当把文件装换为Document后,接下来就是对bean的提取及注册
       * 注册bean定义
       */
      return registerBeanDefinitions(doc, resource);
   }
   //异常捕获
   ...
}

分析:

  1. 将配置文件解析为一个Document实例,以便下面对Bean定义进行解析; 在解析之前会获取资源文件的验证方式(DTD或XSD)
  2. 对bean的提取及注册bean定义

2. 配置资源解析以及根节点的获取

XmlBeanDefinitionReader#registerBeanDefinitions实现:

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
   //实例化BeanDefinitionDocumentReader接口
   BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
   //记录统计前BeanDefinition的加载个数
   int countBefore = getRegistry().getBeanDefinitionCount();
   /**
    * 加载及注册bean
    * {@link org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#registerBeanDefinitions(Document, XmlReaderContext)}
    */
   documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
   //记录本次加载的BeanDefinition个数
   return getRegistry().getBeanDefinitionCount() - countBefore;
}

分析:

  1. 创建Bean定义信息解析器 (DefaultBeanDefinitionDocumentReader)
  2. 加载及注册bean
  3. 返回本次注册Bean定义的数量

DefaultBeanDefinitionDocumentReader#registerBeanDefinitions实现:

@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
   this.readerContext = readerContext;
   logger.debug("Loading bean definitions");
   Element root = doc.getDocumentElement();
   /**
    * 获取节点的根节点,并将root作为参数继续BeanDefinition的注册
    */
   doRegisterBeanDefinitions(root);
}

分析: 获取配置文件的根节点, 开始注册Bean定义信息

3. 注册BeanDefinition

DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions实现:

protected void doRegisterBeanDefinitions(Element root) {
   BeanDefinitionParserDelegate parent = this.delegate;
   this.delegate = createDelegate(getReaderContext(), root, parent);
   ...
   //解析前处理,留给子类实现(设计模式:模板方法模式)
   preProcessXml(root);
   /**
    * 根据Root节点进行解析
    */
   parseBeanDefinitions(root, this.delegate);
   //解析后处理,留给子类实现(设计模式:模板方法模式)
   postProcessXml(root);
   this.delegate = parent;
}

DefaultBeanDefinitionDocumentReader#parseBeanDefinitions实现:

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
   //如果beans是默认命名空间
   if (delegate.isDefaultNamespace(root)) {
      //获取beans的所有子节点,遍历,对其子节点根据是否使用默认命名空间,使用不同的解析方法
      NodeList nl = root.getChildNodes();
      for (int i = 0; i < nl.getLength(); i++) {
         Node node = nl.item(i);
         if (node instanceof Element) {
            Element ele = (Element) node;
            //判断是否是默认命名空间
            if (delegate.isDefaultNamespace(ele)) {
               /**
                * 如果是默认命名空间(对bean的处理)
                */
               parseDefaultElement(ele, delegate);
            }
            else {
               /**
                * 如果不是默认命名空间(对bean的处理)
                */
               delegate.parseCustomElement(ele);
            }
         }
      }
   }
   //如果beans不是默认命名空间
   else {
      delegate.parseCustomElement(root);
   }
}

分析:

  1. 默认命名空间解析
  2. 自定义命名空间解析

3.1 默认命名空间解析

DefaultBeanDefinitionDocumentReader#parseDefaultElement实现:

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
   /**
    * 对import标签进行处理
    */
   if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
      importBeanDefinitionResource(ele);
   }
   /**
    * 对alias标签进行处理
    */
   else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
      processAliasRegistration(ele);
   }
   /**
    * 对bean标签进行处理
    */
   else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
      processBeanDefinition(ele, delegate);
   }
   /**
    * 对beans标签进行处理
    */
   else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
      // recurse  递归
      doRegisterBeanDefinitions(ele);
   }
}

分析:

  1. 对<import>标签进行处理
  2. 对<alias>标签进行处理
  3. 对<bean>标签进行处理(这里只分析<bean>标签的解析)
  4. 对<beans>标签进行处理

3.1.1 <bean>标签处理解析

_3. DefaultBeanDefinitionDocumentReader#processBeanDefinition实现:

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
   /**
    * 1.解析ele,返回BeanDefinitionHolder类型实例bdHolder,经过这个方法后,bdHolder实例已经包含我们配置文件中配置的各种属性,例如:class,name,id,alias等
    */
   BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
   if (bdHolder != null) {
      /**
       * 2.当返回的bdHolder不为空的情况下若存在默认标签的字标签下再有自定义属性,还需要再次对自定义标签进行解析
       */
      bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
      try {
         /**
          * 3.对bdHolder进行注册
          */
         BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
      }
      catch (BeanDefinitionStoreException ex) {
         getReaderContext().error("Failed to register bean definition with name '" +
               bdHolder.getBeanName() + "'", ele, ex);
      }
      //4.发出相应事件,通知相关的监听器,这个bean已经被加载完了
      getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
   }
}

分析:

  1. 解析ele, 返回BeanDefinitionHolder类型实例bdHolder, 经过这个方法后, bdHolder实例已经包含我们配置文件中配置的各种属性, 例如:class,name,id,alias等 
  2. 当返回的bdHolder不为空的情况下若存在默认标签的字标签下再有自定义属性,还需要再次对自定义标签进行解析
  3. 对bdHolder进行注册
  4. 发出相应事件,通知相关的监听器,这个bean已经被加载完了

_3. BeanDefinitionReaderUtils#registerBeanDefinition实现:

public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)throws BeanDefinitionStoreException {
   // 根据主名称注册bean定义信息
   String beanName = definitionHolder.getBeanName();
   /**
    * GenericApplicationContext类实现了BeanDefinitionRegistry接口,
    * 并且在 GenericApplicationContext类中维护了一个DefaultListableBeanFactory beanFactory  (卧槽, 终于见到bean工厂了)
    *
    * 该步骤实际调用的是GenericApplicationContext类中的registerBeanDefinition()方法
    *{@link org.springframework.context.support.GenericApplicationContext#registerBeanDefinition(String,BeanDefinition)}
    */
   registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
   // 如果该bean有别名的话, 为bean名称注册别名
   String[] aliases = definitionHolder.getAliases();
   if (aliases != null) {
      for (String alias : aliases) {
         registry.registerAlias(beanName, alias);
      }
   }
}

分析:

  1. 获取beanName, 注册Bean定义信息时以BeanName为键进行注册
  2. 注册BeanDefinition
  3. 注册别名(key=beanName, value=alias)

_2. GenericApplicationContext类定义信息:

public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
   //bean工厂, 用来注册bean定义信息
   //DefaultListableBeanFactory中维护了一个
   private final DefaultListableBeanFactory beanFactory;
   . . . . . .
}

3.1.2 BeanDefinition的注册

GenericApplicationContext#registerBeanDefinition ==> DefaultListableBeanFactory#registerBeanDefinition实现:

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
   . . . 
   if (beanDefinition instanceof AbstractBeanDefinition) {
      try {
         /**
          * 注册前的最后一次校验,这里的校验不同于之前的XML文件校验
          * 主要是对于AbstracBeanDefinition属性中的methodOverrides校验,
          * 校验methodOverrides是否与工厂方法并存或者methodOverrides对应的方法不存在
          */
         ((AbstractBeanDefinition) beanDefinition).validate();
      }
      . . .
   }
   //判断该beanName是否已经注册 ,根据不同的设置记性处理; (不愧是Spring, 在我模拟的SpringIOC中我管它那么多, 直接覆盖 ,简单粗暴)
   BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
   if (existingDefinition != null) {
      //如果对应的BeanName已经注册且在配置中配置了bean不允许被覆盖,则抛出异常
      . . .
      //注册beanDefinition(将beanDefinition放入map缓存中)
      this.beanDefinitionMap.put(beanName, beanDefinition);
   }
   //处理注册未被注册的beanName的情况
   else {
      /**
        * 检查这个工厂的bean创建阶段是否已经开始,即 是否有任何bean被标记为同时创建。
        * 如果bean工厂的bean创建已经开始, 那么就不能在beanDefinitionNames集合中添加beanName; 因为创建bean时, 会迭代beanDefinitionNames集合,获取beanName,获取BeanDefinition创建bean实例
        * 一旦开始迭代, 则不允许在向该map集合中插入元素
        */
      if (hasBeanCreationStarted()) {
         //处于bean创建阶段
         //因为beanDefinitionMap是全局变量,这里肯定会存在并发访问的情况
         synchronized (this.beanDefinitionMap) {
            //注册beanDefinitionv
            this.beanDefinitionMap.put(beanName, beanDefinition);
            //创建新的集合来更新存储已注册beanName的beanDefinitionNames集合
            List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
            updatedDefinitions.addAll(this.beanDefinitionNames);
            updatedDefinitions.add(beanName);
            this.beanDefinitionNames = updatedDefinitions;
            //更新manualSingletonNames(存储单例bean)集合
            if (this.manualSingletonNames.contains(beanName)) {
               Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
               updatedSingletons.remove(beanName);
               this.manualSingletonNames = updatedSingletons;
            }
         }
      }
      //仍处于注册阶段
      else {
         //将beanName和bean的定义信息加入beanDefinitionMap集合
         this.beanDefinitionMap.put(beanName, beanDefinition);
         //bean定义名称列表,按注册顺序排列
         this.beanDefinitionNames.add(beanName);
         //手动注册的单例程序的名称列表,按注册顺序排列
         this.manualSingletonNames.remove(beanName);
      }
      this.frozenBeanDefinitionNames = null;
   }
   //如果该bean定义已经注册,并且为单例,则进行重置
   if (existingDefinition != null || containsSingleton(beanName)) {
      resetBeanDefinition(beanName);
   }
}

分析:

  1. 注册前的最后一次校验,这里的校验不同于之前的XML文件校验, 主要是对于AbstracBeanDefinition属性中的methodOverrides校验, 校验methodOverrides是否与工厂方法并存或者methodOverrides对应的方法不存在
  2. 判断该beanName是否已经注册; 如果beanName已经注册过: 根据不同的设置进行处理(是否允许覆盖, 如果不允许,则抛出异常; 允许的话, 则进行注册)
  3. 如果beanName没有被注册过; 则开始检查这个工厂的bean创建阶段是否已经开始,即是否有任何bean被标记为同时创建。如果bean工厂的bean创建已经开始,  那么就不能在beanDefinitionNames集合中添加beanName;  因为创建bean时,  会迭代beanDefinitionNames集合,  获取beanName, 获取BeanDefinition创建bean实例;  一旦开始迭代, 则不允许在向该list集合中插入元素,  但是beanDefinitionMap集合可以,  因为beanDefinitionMap集合并没有被迭代,  而是通过beanName获取BeanDefinition信息;
  4. 如果该bean定义已经注册, 并且为单例, 则进行重置

3.2 自定义命名空间解析

BeanDefinitionParserDelegate#parseCustomElement实现:

public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
   /**spring.handler:
    *           http\://www.lic.com/schema/user=test.MyNameSpaceHandler
    *                  命名空间                NamespaceHandler
    */

   /**
    * 1.获取对应的命名空间
    */
   String namespaceUri = getNamespaceURI(ele);
   if (namespaceUri == null) {
      return null;
   }
   /**
    * 2.根据命名空间找到对应的NameSpaceHandler,用来解析XSD文件中的定义和组件定义
    * {@link org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver#resolve(java.lang.String)}
    */
   NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
   if (handler == null) {
      error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
      return null;
   }
   /**
    * 3.调用自定义的NamespaceHandler进行解析
    * {@link NamespaceHandlerSupport#parse(Element, ParserContext)}
    */
   return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}

分析:

  1. 获取对应的命名空间
  2. 根据命名空间找到对应的NameSpaceHandler, 用来解析XSD文件中的定义和组件定义
  3. 调用自定义的NamespaceHandler进行解析

3.2.1 获取名称处理器

_2. DefaultNamespaceHandlerResolver#resolve

public NamespaceHandler resolve(String namespaceUri) {
   /**
    * 获取所有已经配置的handler映射
    */
   Map<String, Object> handlerMappings = getHandlerMappings();
   //根据命名空间找到对应的信息
   Object handlerOrClassName = handlerMappings.get(namespaceUri);
   if (handlerOrClassName == null) {
      return null;
   }
   else if (handlerOrClassName instanceof NamespaceHandler) {
      //已经做过解析的情况,直接从缓存读取
      return (NamespaceHandler) handlerOrClassName;
   }
   else {
      //没有做过解析,则返回的是类路径
      String className = (String) handlerOrClassName;
      try {
         //利用反射将类路径转换为类
         Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
         ...
         //初始化类
         NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
         /**
          * 调用自定义的NamespaceHandler的初始化方法
          * SpringMvc: {@link org.springframework.web.servlet.config.MvcNamespaceHandler#init()}
          */
         namespaceHandler.init();
         //将该handler记录在缓存中,以便下次调用该handler可以直接获取,不用再次转换
         handlerMappings.put(namespaceUri, namespaceHandler);
         return namespaceHandler;
      }
      ...
   }
}

分析:

  1. 获取所有已经配置的handler映射
  2. 根据命名空间找到对应的信息
  3. 已经做过解析的情况,直接从缓存读取; 没有做过解析,则返回的是类路径,利用反射将类路径转换为类
  4. 调用自定义的NamespaceHandler的初始化方法; 初始化NamespaceHandler

示例: SpringMvc的名称空间解析器初始化方法:

@Override
public void init() {
   /**
    * 将标签名称与对应解析器关联
    *
    * 第一次尝试获取MvcNamespaceHandler时会调用该初始化方法进行初始化
    */
   registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
   registerBeanDefinitionParser("default-servlet-handler", new DefaultServletHandlerBeanDefinitionParser());
   registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());
   registerBeanDefinitionParser("resources", new ResourcesBeanDefinitionParser());
   registerBeanDefinitionParser("view-controller", new ViewControllerBeanDefinitionParser());
   registerBeanDefinitionParser("redirect-view-controller", new ViewControllerBeanDefinitionParser());
   registerBeanDefinitionParser("status-controller", new ViewControllerBeanDefinitionParser());
   registerBeanDefinitionParser("view-resolvers", new ViewResolversBeanDefinitionParser());
   registerBeanDefinitionParser("tiles-configurer", new TilesConfigurerBeanDefinitionParser());
   registerBeanDefinitionParser("freemarker-configurer", new FreeMarkerConfigurerBeanDefinitionParser());
   registerBeanDefinitionParser("groovy-configurer", new GroovyMarkupConfigurerBeanDefinitionParser());
   registerBeanDefinitionParser("script-template-configurer", new ScriptTemplateConfigurerBeanDefinitionParser());
   registerBeanDefinitionParser("cors", new CorsBeanDefinitionParser());
}

 

_3. NamespaceHandlerSupport#parse实现:

public BeanDefinition parse(Element element, ParserContext parserContext) {
   /**
    * 寻找解析器并进行解析操作,在自定义handler中并没有重写父类中parse()方法,因此此处是调用父类AbstractBeanDefinitionParser中的parse()方法
    *
    * 在parse()方法中根据标签命名空间获取不同的解析进行解析
    * 例如: 标签:<context:component-scan base-package="com.ioc.lic"/>的解析为ComponentScanBeanDefinitionParser
    * 该解析器会去解析包路径信息, 注册包路径下的所有BeanDefinition
    */
   BeanDefinitionParser parser = findParserForElement(element, parserContext);
   /**
    * 解析器1:
    * {@link AbstractBeanDefinitionParser#parse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)}
    * 解析器2:<context:component-scan base-package="com.ioc.lic"/>
    * {@link org.springframework.context.annotation.ComponentScanBeanDefinitionParser#parse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)}
    */
   return (parser != null ? parser.parse(element, parserContext) : null);
}

分析:

  1. 根据不同的定义标签获取对应的解析器进行解析
  2. 调用解析器中的parse()解析该标签 (这里以<context:component-scan base-package="com.ioc.lic"/>标签为例进行分析)

3.2.2 根据标签名称获取解析器

_1.NamespaceHandlerSupport#findParserForElement实现:

private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
   //获取元素名称,也就是<myname:user>中的user,若在实例中,此时localName为user
   String localName = parserContext.getDelegate().getLocalName(element);
   //根据user找到对应的解析器,也就是在 registerBeanDefinitionParser("user", new UserBeanDefinitionParser())  中注册的解析器
   BeanDefinitionParser parser = this.parsers.get(localName);
   if (parser == null) {
      parserContext.getReaderContext().fatal(
            "Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
   }
   return parser;
}

3.2.3 解析自定义标签

ComponentScanBeanDefinitionParser#parse实现:

public final BeanDefinition parse(Element element, ParserContext parserContext) {
   /**
    * 解析element
    * {@link AbstractSingleBeanDefinitionParser#parseInternal(Element, ParserContext)}
    */
   AbstractBeanDefinition definition = parseInternal(element, parserContext);
   if (definition != null && !parserContext.isNested()) {
      try {
         ...
         //将AbstractBeanDefinition装换成BeanDefinitionHolder并注册
         BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, id, aliases);
         //注册
         registerBeanDefinition(holder, parserContext.getRegistry());
         if (shouldFireEvents()) {
            //需要通知监听器进行处理
            BeanComponentDefinition componentDefinition = new BeanComponentDefinition(holder);
            postProcessComponentDefinition(componentDefinition);
            parserContext.registerComponent(componentDefinition);
         }
      }
      ...
   }
   return definition;
}

分析: 

  1. 获取到包路径信息
  2. 配置扫描器, 扫描包路径, 注册BeanDefinition

ClassPathBeanDefinitionScanner#doScan实现:

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
   Assert.notEmpty(basePackages, "At least one base package must be specified");

   //存储扫描到的BeanDefinition信息
   Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();

   /**
    * 循环遍历包路径信息,进行解析,注册
    */
   for (String basePackage : basePackages) {
      /**
       * 扫描出该包路径下左右的候选Bean
       */
      Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
      /**
       * 对所有的候选bean进行解析
       */
      for (BeanDefinition candidate : candidates) {
         //获取Scope属性
         ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
         candidate.setScope(scopeMetadata.getScopeName());
         //根据Bean信息生成BeanName
         String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);

         //对于配置类型BeanDefinition类型和注解类型BeanDefinition类型进行区分设置
         if (candidate instanceof AbstractBeanDefinition) {
            /**
             * 如果这个类是AbstractBeanDefinition的子类
             * 则为他设置默认值,比如lazy,init destory
             */
            postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
         }
         if (candidate instanceof AnnotatedBeanDefinition) {
            /**
             * 检查并且处理常用的注解
             * 这里的处理主要是指把常用注解的值设置到AnnotatedBeanDefinition当中
             * 当前前提是这个类必须是AnnotatedBeanDefinition类型的,说白了就是加了注解的类
             */
            AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
         }

         //判断注册器中是否已经存在该BeanName
         if (checkCandidate(beanName, candidate)) {
            BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
            definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
            beanDefinitions.add(definitionHolder);
            /**
             * 注册BeanDefinition
             */
            registerBeanDefinition(definitionHolder, this.registry);
         }
      }
   }
   return beanDefinitions;
}

至此, 使用XmlBeanFactory来初始化IOC容器解析完成;

 

相关文章:

     Spring源码解析一 (IOC容器初始化深度解析)

     Spring源码解析二 (IOC容器初始化方式一:XmlBeanFactory)

     Spring源码解析三 (IOC容器初始化方式二:ClassPathXmlApplicationContext)

     Spring源码解析四 (IOC容器初始化方式三: AnnotationConfigApplicationContext[包路径配置方式])

     Spring源码解析五 (IOC容器初始化方式四: AnnotationConfigApplicationContext[Java配置类方式])

     Spring源码解析六 (Bean的初始化)

     Spring源码解析七 (AOP深度解析)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值