首页 > 其他分享 >核心子方法2: obtainFreshBeanFactory()方法详解

核心子方法2: obtainFreshBeanFactory()方法详解

时间:2024-02-26 17:45:38浏览次数:37  
标签:bd 标签 ele alias bean 详解 obtainFreshBeanFactory 解析 方法

先总结: 该方法new了一个beanFactory, 设置了一些忽略的接口, 加载并解析了bean.xml, 主要将bean信息解析为BeanDefinition保存到beanFactory中

1.refreshBeanFactory()方法

   1.1 创建DefaultListableBeanFactory对象: createBeanFactory() -> new DefaultListableBeanFactory(getInternalParentBeanFactory());

  1.2 定制beanFactory,设置相关属性,包括是否允许覆盖同名称的不同定义的对象以及循环依赖: customizeBeanFactory(beanFactory);

 

   1.3 初始化documentReader,并进行XML文件读取及解析,默认命名空间的解析,自定义标签的解析: loadBeanDefinitions(beanFactory);  注意: 解析xml核心方法

    创建一个xml的beanDefinitionReader,并通过回调设置到beanFactory中:

      XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory)

    给reader对象设置环境对象: beanDefinitionReader.setEnvironment(this.getEnvironment());

    beanDefinitionReader.setResourceLoader(this);

    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

    初始化beanDefinitionReader对象,此处设置配置文件是否要进行验证: initBeanDefinitionReader(beanDefinitionReader);

    始完成beanDefinition的加载: loadBeanDefinitions(beanDefinitionReader);

      通过XmlBeanDefinitionReader对象, 遍历加载所有xml配置文件:

       loadBeanDefinitions

      -> loadBeanDefinitions(new EncodedResource(resource));

      -> doLoadBeanDefinitions(inputSource, encodedResource.getResource());  //xml解析核心步骤

      -> Document doc = doLoadDocument(inputSource, resource);  //获取xml文件的document对象

        int count = registerBeanDefinitions(doc, resource);  //解析document对象, 封装成一个个的BeanDefinition对象

      -> BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();

        documentReader.registerBeanDefinitions(doc, createReaderContext(resource));

      -> doRegisterBeanDefinitions(doc.getDocumentElement());

      -> preProcessXml(root);

       parseBeanDefinitions(root, this.delegate);  //从根节点标签开始解析

       postProcessXml(root);

      -> parseDefaultElement(ele, delegate);  //解析默认元素标签: <beans></beans>

       delegate.parseCustomElement(ele);  //解析自定义元素标签

        --> 默认标签解析

          if (delegate.nodeNameEquals(ele,"import")) {

            importBeanDefinitionResource(ele);  //处理import标签元素

          }else if (delegate.nodeNameEquals(ele, "alias")) {

            processAliasRegistration(ele);  //处理alias标签元素

          }else if (delegate.nodeNameEquals(ele,"alias")) {

              processBeanDefinition(ele, delegate);  //处理bean标签元素

          }else if (delegate.nodeNameEquals(ele,"beans")) {

              doRegisterBeanDefinitions(ele);  //递归处理beans标签元素

          }

          --->  处理import标签元素

            String location = ele.getAttribute("resource");  //获取resource属性

            location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);  //通过之前加载的系统环境变量替换字符串中的如: ${user.dir}的变量

            boolean absoluteLocation = false;

            try {

              absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute(); //判断location是绝对URI还是相对URI, classpath*:开头的为绝对路径

            }

            //如果是绝对URI则直接根据地址加载对应的配置文件

              getReaderContext().getReader().loadBeanDefinitions(location, actualResources);

            //如果是相对路径,则根据相对地址计算出绝对地址

              getReaderContext().getReader().loadBeanDefinitions(relativeResource);

            //解析后进行监听器激活处理

          --->   处理alias标签元素

              String name = ele.getAttribute(''name");  //获取beanName

              String alias = ele.getAttribute("alias");  //获取alias

              getReaderContext().getRegistry().registerAlias(name, alias);  //注册alias

              getReaderContext().fireAliasRegistered(name, alias, extractSource(ele));  //别名注册后通知监听器做相应处理

          --->   处理bean标签元素

              beanDefinitionHolder是beanDefinition对象的封装类,封装了BeanDefinition,bean的名字和别名,用它来完成向IOC容器的注册, 

              得到beanDefinitionHolder就意味着beandefinition是通过BeanDefinitionParserDelegate对xml元素的信息按照spring的bean规则进行解析得到

              BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);

              BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());  //向ioc容器注册解析得到的beandefinition的地方

              getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));  //在beandefinition向ioc容器注册完成之后,发送消息

              ---->  <bean>标签解析处理

                  String id = ele.getAttribute("id");  //解析id属性

                  String nameAttr = ele.getAttribute("name");  //解析name属性

                  AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);  //对bean元素的详细解析

                  return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);  //封装为BeanDefinitionHolder返回

                -----> 对bean元素的详细解析

                  className = ele.getAttribute("class").trim();

                  parent = ele.getAttribute("parent");

                  AbstractBeanDefinition bd = createBeanDefinition(className, parent);  //创建装在bean信息的AbstractBeanDefinition对象,实际的实现是GenericBeanDefinition -> BeanDefinitionReaderUtils.createBeanDefinition(parentName, className, this.readerContext.getBeanClassLoader()); -> GenericBeanDefinition bd = new GenericBeanDefinition(); bd.setBeanClass(ClassUtils.forName(className, classLoader));

                  parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);  //解析bean标签的各种其他属性

                  bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));  //设置description信息

                  parseMetaElements(ele, bd);  //解析元数据

                  parseLookupOverrideSubElements(ele, bd.getMethodOverrides());  //解析lookup-method属性

                  parseReplacedMethodSubElements(ele, bd.getMethodOverrides());  //解析replaced-method属性

                  parseConstructorArgElements(ele, bd);  //解析构造函数参数

                  parsePropertyElements(ele, bd);  //解析property子元素

                  parseQualifierElements(ele, bd);  //解析qualifier子元素

                  bd.setResource(this.readerContext.getResource());

                  bd.setSource(extractSource(ele));

        --> 自定义标签解析

          String namespaceUri = getNamespaceURI(ele);  //获取对应的命名空间

 

 

          NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);  //根据命名空间找到对应的NamespaceHandlerspring, 如: 

 

          handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));  //调用自定义的NamespaceHandler进行解析

 

 

上面几步总结,  解析过程是由documentLoader完成的, 从String[] -> String -> Resource[] > Resource, 最终将resource读取成一个document文档,根据document文档的节点信息, 封装成一个个的BeanDefinition对象;

      

 

标签:bd,标签,ele,alias,bean,详解,obtainFreshBeanFactory,解析,方法
From: https://www.cnblogs.com/superpiter/p/18031587

相关文章

  • 系统科学方法概论第二章读后感
    阅读了《系统科学方法概论》的第二章,对系统工程方法有了基本的理解和认识。这一章节为初学者提供了系统科学的入门级指导,为对系统科学感兴趣的读者构建起对该领域的基本理解和认识。首先,我深刻地认识到系统科学的重要性。在解决现代社会中的复杂问题方面具有重要的应用价值。在我......
  • 系统科学方法概论第三章读后感
    第三章信息方法从信息的视角探讨了系统科学方法中的重要一环。让读者对该方法有了更加深入的认识。信息方法在系统科学中具有显著的优势。首先,它强调信息的准确性和完整性,这有助于减少信息失真和不确定性,从而提高决策的准确性。其次,信息方法为多学科交叉提供了平台,使得不同领域的......
  • Python中字典setdefault()方法和append()的配合使用
    1.setdefault()方法语法dict.setdefault(key,default=None)说明:如果字典中包含给定的键值,那么返回该键对应的值。否则,则返回给定的默认值。Syntax:dict.setdefault(key,default_value)Parameters:Ittakestwoparameters:key–Keytobesearchedinthedictionar......
  • Linux下修改挂载点的操作方法(linux修改挂载点)
    Linux下修改挂载点的操作方法 Linux是一款多用途操作系统,具备很强的功能。很多时候,我们需要修改Linux下的挂载点,以便让挂载点更加合理、方便文件访问等。下面就介绍在Linux下修改挂载点的操作方法。 首先,我们需要获取已经挂载的设备名称,可以通过以下指令来实现: df-h //......
  • 《系统科学方法概论》第一章
    这一章不仅为我提供了系统科学的基本概念和原理,更重要的是,它让我对如何运用系统科学的方法去理解和解决问题有了全新的认识。我深刻体会到,系统科学不仅仅是一种科学的研究方法,更是一种全新的思维方式和解决问题的工具。它教会我如何从整体和全局的角度去看待问题,而不是仅仅局限于......
  • 《系统科学方法概论》第三章
    在本章,通过作者的介绍,我了解到了信息科学的发展历史以及什么是信息和信息量,还有信息的属性以及如何感知信息发展的规律性,还有信息发展的基础及信息技术,除此之外,我还知道了两种信息方法,即利用信息认识事物的方法和利用信息改造事物的方法。笔者认为,人类的一切活动归根结底就是认识......
  • 网站图片防盗链的几种方法
    1.通过URLRewriteModule 组件这是一个比较简单,方便的方法。首先要去 UrlRewite官网 下载URLRewriteModule2.0并安装。安装完成后可以看到IIS设置里多了 URL重写,在这里,可以对URL访问规则进行设置。2.通过nginx 图片防盗链3.自定义HttpHandler处理方法步......
  • 自主系统方法
      自组织系统理论的发展史:1、19世纪中期热力学的主要成就及其理论意义2、19世纪热力学与现实的矛盾3、19世纪以来科学家们对热力学与生物学矛盾的解决 系统分类有三种:1、孤立系统2、封闭系统3、开放系统 耗散结构:是指一个远离平衡状态的开放系统当外界条件变化到一......
  • 《系统科学方法概论》——第四章 控制方法
    一、控制论史1、控制论的发展史(一)、古代控制论:在古代人们通过运用机关结构实现控制,造出了自动装置。(二)、近代的控制论萌芽:近代的控制论萌芽主要是在机械化大生产之上产生的自动调速技术和后来发展成的伺服机理论。(1)自动调速技术。自动调速技术的发明对机械化大生产起了很大促......
  • 信息方法
       信息科学主要是在通信实践基础上发展起来的一门科学,从人类社会诞生的那一天起,通信就成为人类离不开的东西。从语言到文字,从短距离到长距离,通信适应着生产生活的需要,不断发展。近代通信技术首先是从有线电通信发展起来的,现在以来,人们逐步对通信实践中的技术与问题展开了深......