深入理解Spring IOC(二) 、从xml到BeanDefinition(下)

简介: 深入理解Spring IOC(二) 、从xml到BeanDefinition(下)

ClassPathApplicationContext 和 BeanDefinitionReader


我们上一篇开始有这么一段代码不知道大家还记得不:


public static void main(String[] args) {
        ApplicationContext applicationContext =
                new ClassPathXmlApplicationContext("classpath*:application-context.xml");
        ATest aTest = applicationContext.getBean(ATest.class);
        aTest.doSomeThing();
}


这段代码中ClassPathApplicationContext将我们的xml加载解析成了beanDefinition对象,并且转换成了最终的bean,我们经过前面的学习已经知道了XmlBeanDefinitionReader是怎样把xml解析成beanDefinition对象的,那么,在上面这段代码运行的时候,这个解析过程是发生在哪里呢?我们一起来看看ClassPathApplicationContext的构造方法:


代码块21
        public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
    // 调用的是下边的这个方法
    this(new String[] {configLocation}, true, null);
  }
  public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
      throws BeansException {
    super(parent);
    // 解析配置,此时参数是[classpath*:application-context.xml]
    setConfigLocations(configLocations);
    if (refresh) {
            // 调用下面的refresh方法
      refresh();
    }
  }



注意哈:这里我暂时只放refresh的前几行代码,因为其他的还和我们目前讲的没关系


代码块22
        @Override
  public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
      // 1.加载前的准备工作
      prepareRefresh();
      // 2.获取一个全新的beanFactory实例
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
      // 3.初始化beanFactory,给它设置各种
      prepareBeanFactory(beanFactory);


仅仅放出来了开始的那几行代码,是因为我们目前所说到的,也就和这个第二句有关系,我们直接来看2中的obtainFreshBeanFactory,它也是在AbstractApplicationContext中,


代码块23
        protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
                // 重点
    refreshBeanFactory();
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (logger.isDebugEnabled()) {
      logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
    }
    return beanFactory;
  }


重点是这第一行的这个方法,这个方法也是AbstractApplicationContext,但是它是个抽象方法,真正的实现是在AbstractRefreshableApplicationContext中,我们直接来看这里的refreshBeanFactory方法:


代码块24
        @Override
  protected final void refreshBeanFactory() throws BeansException {
    if (hasBeanFactory()) {
      destroyBeans();
      closeBeanFactory();
    }
    try {
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      beanFactory.setSerializationId(getId());
      customizeBeanFactory(beanFactory);
      // 加载BeanDefinition的
      loadBeanDefinitions(beanFactory);
      synchronized (this.beanFactoryMonitor) {
        this.beanFactory = beanFactory;
      }
    }
    catch (IOException ex) {
      throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
  }


上面代码块中只有一句我给了注释,那个其实也是个抽象方法,真正的实现是在子类AbstractXmlApplicationContext中,我们到AbstractXmlApplicationContext中来:


代码块25
        @Override
  protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    // 1.我们前文所说过的XmlBeanDefinitionReader
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
    // 2.现在是在AbstractXmlApplicationContext,其父类既继承了DefaultResourceLoader的,也
    // 实现了ResourcePatternResolver
    beanDefinitionReader.setEnvironment(this.getEnvironment());
    beanDefinitionReader.setResourceLoader(this);
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
    // 3.设置验证模型
    initBeanDefinitionReader(beanDefinitionReader);
    // 4.加载Resource
    loadBeanDefinitions(beanDefinitionReader);
  }

我们在这里直接就可以看到,ClassPathXmlApplicationContext就是用的XmlBeanDefinitionReader来加载解析Resource的,我们来看看上面代码块中3处的代码


代码块26
        protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) {
    reader.setValidating(this.validating);
  }


它调用的是XmlBeanDefinitionReader的内部方法,注意参数中this.validating的值是true,我们跟到这个方法中:


代码块27
        public void setValidating(boolean validating) {
    this.validationMode = (validating ? VALIDATION_AUTO : VALIDATION_NONE);
    this.namespaceAware = !validating;
  }


哈哈,这下应该是知道之前代码块7和8那里大量出现的validationMode的值是怎么来的了吧,其实就是在这里给赋值的,表示让程序去发现到底该使用怎样的解析方式。最后我们再来看看代码块25中4处的代码


代码块28
        protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
    Resource[] configResources = getConfigResources();
    if (configResources != null) {
      reader.loadBeanDefinitions(configResources);
    }
    // 实际走的是这里,因为上面的configResources此时是null
    String[] configLocations = getConfigLocations();
    if (configLocations != null) {
      reader.loadBeanDefinitions(configLocations);
    }
  }


这个方法调用的就是我们前文所说过的XmlBeanDefinitionReader中的方法了,至此,xml怎样解析成BeanDefinition就已经说完,我们把我们到现在为止说到过的东西总结成下面的这张图:


1686810712641.png


我们可以看到,本篇讲的,其实就是最下面这部分的,下篇我们说从BeanDefinition是怎样变成Bean实例的。

目录
相关文章
|
4天前
|
XML Java 数据格式
Spring框架入门:IoC与DI
【5月更文挑战第15天】本文介绍了Spring框架的核心特性——IoC(控制反转)和DI(依赖注入)。IoC通过将对象的创建和依赖关系管理交给容器,实现解耦。DI作为IoC的实现方式,允许外部注入依赖对象。文章讨论了过度依赖容器、配置复杂度等常见问题,并提出通过合理划分配置、使用注解简化管理等解决策略。同时,提醒开发者注意过度依赖注入和循环依赖,建议适度使用构造器注入和避免循环引用。通过代码示例展示了注解实现DI和配置类的使用。掌握IoC和DI能提升应用的灵活性和可维护性,实践中的反思和优化至关重要。
18 4
|
4天前
|
Java 测试技术 开发者
Spring IoC容器通过依赖注入机制实现控制反转
【4月更文挑战第30天】Spring IoC容器通过依赖注入机制实现控制反转
22 0
|
4天前
|
XML Java 程序员
Spring特性之二——IOC控制反转
Spring特性之二——IOC控制反转
16 4
|
4天前
|
XML Java 数据格式
Spring高手之路18——从XML配置角度理解Spring AOP
本文是全面解析面向切面编程的实践指南。通过深入讲解切面、连接点、通知等关键概念,以及通过XML配置实现Spring AOP的步骤。
22 6
Spring高手之路18——从XML配置角度理解Spring AOP
|
4天前
|
安全 Java 开发者
在Spring框架中,IoC和AOP是如何实现的?
【4月更文挑战第30天】在Spring框架中,IoC和AOP是如何实现的?
24 0
|
4天前
|
XML Java 程序员
什么是Spring的IoC容器?
【4月更文挑战第30天】什么是Spring的IoC容器?
20 0
|
4天前
|
Java Spring 容器
【Spring系列笔记】IOC与DI
IoC 和 DI 是面向对象编程中的两个相关概念,它们主要用于解决程序中的依赖管理和解耦问题。 控制反转是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入和依赖查找。
35 2
|
4天前
|
XML Java 数据格式
④【Spring】IOC - 基于注解方式 管理bean
④【Spring】IOC - 基于注解方式 管理bean
51 0
|
4天前
|
XML Java 数据格式
②【Spring】一文精通:IOC - 基于XML方式管理Bean
②【Spring】一文精通:IOC - 基于XML方式管理Bean
147 0
|
4天前
|
XML Java 数据格式
掌握 Spring IoC 容器与 Bean 作用域:详解 singleton 与 prototype 的使用与配置
在您的应用程序中,由 Spring IoC 容器管理的形成其核心的对象被称为 "bean"。一个 bean 是由 Spring IoC 容器实例化、组装和管理的对象
50 0