• Spring 源码阅读 04:BeanFactory 初始化


    本篇要阅读的是 BeanFactory 初始化的部分,也就是 refresh 方法中的这一行方法调用:

    1. // Tell the subclass to refresh the internal bean factory.
    2. // 这里会调用模版方法,通过子类的实现,初始化 BeanFactory 并解析 XML 配置
    3. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

    这里调用了 obtainFreshBeanFactory 并得到了一个 ConfigurableListableBeanFactory 类型的 beanFactory。这个方法的作用是初始化 beanFactory ,还会解析 XML 中配置的 Bean。

    我们先看源码:

    1. /**
    2. * Tell the subclass to refresh the internal bean factory.
    3. * @return the fresh BeanFactory instance
    4. * @see #refreshBeanFactory()
    5. * @see #getBeanFactory()
    6. */
    7. protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    8. refreshBeanFactory();
    9. return getBeanFactory();
    10. }

    这个方法的源码很简单,调用了两个方法,并将第二个方法的结果返回。根据方法的名称可以看到,第一个方法用来刷新(或者初始化)beanFactory,第二个方法用来获取 beanFactory 并返回。

    refreshBeanFactory 方法

    我们先看 refreshBeanFactory 方法,具体实现过程可以在 AbstractRefreshableApplicationContext 类找到 :

    1. /**
    2. * This implementation performs an actual refresh of this context's underlying
    3. * bean factory, shutting down the previous bean factory (if any) and
    4. * initializing a fresh bean factory for the next phase of the context's lifecycle.
    5. */
    6. @Override
    7. protected final void refreshBeanFactory() throws BeansException {
    8. if (hasBeanFactory()) {
    9. destroyBeans();
    10. closeBeanFactory();
    11. }
    12. try {
    13. DefaultListableBeanFactory beanFactory = createBeanFactory();
    14. beanFactory.setSerializationId(getId());
    15. customizeBeanFactory(beanFactory);
    16. loadBeanDefinitions(beanFactory);
    17. synchronized (this.beanFactoryMonitor) {
    18. this.beanFactory = beanFactory;
    19. }
    20. }
    21. catch (IOException ex) {
    22. throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    23. }
    24. }

    从方法的整体流程可以看出,不管当前是不是存在一个 BeanFactory ,这里都会创建一个新的,并进行初始化,我们来逐行分析代码。

    销毁已有的 BeanFactory

    一开始,会判断当前是否存在一个 BeanFactory,如果有的话,就销毁其中的 Bean,并关闭 BeanFactory。这部分逻辑对应方法体开头的 if 语句块。因为我们分析的是 Spring 容器第一次创建时候的流程,而且之前并没有 BeanFactory 创建的逻辑,所以,目前为止,并不存在一个 BeanFactory,if 语句中的逻辑不会被执行。

    实例化新的 BeanFactory

    接下来就是 try 语句块中的部分。

    首先,执行了 createBeanFactory 方法,创建了一个 BeanFactory。这里的代码也很简单:

    1. protected DefaultListableBeanFactory createBeanFactory() {
    2. return new DefaultListableBeanFactory(getInternalParentBeanFactory());
    3. }

    获取到 parent 后,调用构造方法,创建了一个 DefaultListableBeanFactory 的实例并返回。

    DefaultListableBeanFactory 这个类型是第一次见到,我们可以大致看一下它的继承关系:

    这里的接口实现关系错综复杂,可以先看看留个印象。值得一提的是,它的子类 XmlBeanFactory 是 Spring 中非常重要的一个类,是 Spring 的初级容器。如果使用 XML 配置文件来直接创建 BeanFactory 使用的就是 XmlBeanFactory ,不过现在这个类已经被标记了 @Deprecated

    言归正传,回到 refreshBeanFactory 方法中来。创建好 BeanFactory 后,通过 beanFactory.setSerializationId(getId()) 给了它一个 Id,序列化和反序列化的时候用。

    对 BeanFactory 进行自定义

    接下来,customizeBeanFactory(beanFactory) 执行了 ApplicationContext 对内部的 BeanFactory 的自定义。

    1. protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
    2. if (this.allowBeanDefinitionOverriding != null) {
    3. beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
    4. }
    5. if (this.allowCircularReferences != null) {
    6. beanFactory.setAllowCircularReferences(this.allowCircularReferences);
    7. }
    8. }

    这里通过给 beanFactory 的成员变量赋值,做了两件事:

    • 允许相同名称的 BeanDefinition 在容器中被覆盖
    • 允许多个 Bean 之间存在循环依赖

    这两点涉及到了 BeanDefinition 和 Bean 初始化的流程。

    加载 BeanDefinition

    最后一个方法调用,loadBeanDefinitions(beanFactory); 执行了 BeanDefinition 的加载。这里的实现逻辑可以在 AbstractXmlApplicationContext 中找到:

    1. /**
    2. * Loads the bean definitions via an XmlBeanDefinitionReader.
    3. * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
    4. * @see #initBeanDefinitionReader
    5. * @see #loadBeanDefinitions
    6. */
    7. @Override
    8. protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    9. // Create a new XmlBeanDefinitionReader for the given BeanFactory.
    10. XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
    11. // Configure the bean definition reader with this context's
    12. // resource loading environment.
    13. beanDefinitionReader.setEnvironment(this.getEnvironment());
    14. beanDefinitionReader.setResourceLoader(this);
    15. beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
    16. // Allow a subclass to provide custom initialization of the reader,
    17. // then proceed with actually loading the bean definitions.
    18. initBeanDefinitionReader(beanDefinitionReader);
    19. loadBeanDefinitions(beanDefinitionReader);
    20. }

    在这个方法中,首先创建了一个 XmlBeanDefinitionReader 的实例,并对其进行了配置。从它的名字可以知道,这个类用来读取 XML 中的 Bean 定义。

    创建好之后,末尾调用了两个方法,我们先看 initBeanDefinitionReader 的源码:

    1. protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) {
    2. reader.setValidating(this.validating);
    3. }

    方法名告诉我们方法的作用是对 XmlBeanDefinitionReader 进行初始化,这里只是设置了是否对 XML 文件进行验证(默认值是 true),其余什么也没干。我们还注意到,这个方法是 protected 修饰的,因此可以断定,这里是 Spring 留给我们的一个扩展点。我们可以通过重写这个方法,关闭 XML 验证、自定义 XML 的解析器,或者执行其他的一些设置。

    最后将 beanDefinitionReader 作为参数,调用了另外一个 loadBeanDefinitions 方法。源码如下:

    1. protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
    2. Resource[] configResources = getConfigResources();
    3. if (configResources != null) {
    4. reader.loadBeanDefinitions(configResources);
    5. }
    6. String[] configLocations = getConfigLocations();
    7. if (configLocations != null) {
    8. reader.loadBeanDefinitions(configLocations);
    9. }
    10. }

    在这里,分别将 configResources 和 configLocations 作为参数,执行了 reader 的 loadBeanDefinitions 方法。不过,getConfigResources 这个方法直接返回了 null,因此,这里的逻辑就是,根据我们创建 ClassPathXmlApplicationContext 时提供的配置文件路径,进行 BeanDefinition 的加载。

    ~~这里 reader.loadBeanDefinitions 方法加载 BeanDefinition 的逻辑是现在 AbstractBeanDefinitionReader#loadBeanDefinitions(java.lang.String...) 方法中

    完成初始化并赋值

    方法的末尾,通过 this.beanFactory = beanFactory; 将之前创建并初始化好的 BeanFactory 赋值给 beanFactory 成员变量。

    getBeanFactory 方法

    最后我们在回到最开始的 obtainFreshBeanFactory 方法,看一下里面调用的第二个方法 getBeanFactory() 的源码,实现逻辑在 AbstractRefreshableApplicationContext 类中:

    1. @Override
    2. public final ConfigurableListableBeanFactory getBeanFactory() {
    3. synchronized (this.beanFactoryMonitor) {
    4. if (this.beanFactory == null) {
    5. throw new IllegalStateException("BeanFactory not initialized or already closed - " +
    6. "call 'refresh' before accessing beans via the ApplicationContext");
    7. }
    8. return this.beanFactory;
    9. }
    10. }

    这里其实就是把 refreshBeanFactory 方法创建并初始化的 BeanFactory 获取到并返回。

     

  • 相关阅读:
    智慧工地源代码 SaaS模式云平台
    Flink 运行架构和核心概念
    新员工webpack打包后上传服务器页面空白
    vs调用python PyImport_ImportModule返回为0的处理
    Loongnix-server中ovirt-engine-4.4安装及使用方法
    Arthas调优工具使用
    使用yolov8 进行实例分割训练
    《计算机体系结构量化研究方法》1.7 可信任度
    一加11/Ace2/10Pro手机如何实现全局120HZ高刷-游戏超级流畅效果
    Linux网络驱动
  • 原文地址:https://blog.csdn.net/jcc4261/article/details/128011354