上一篇咱们通过一个例子介绍初始化容器上下文相关内容,并通过两个示例代码看到了Spring在设计阶段为我预留的扩展点,和我们应该如何利用这两个扩展点在Spring初始化容器上下文阶段为我们提供服务。这一篇咱们接着往下看。
老这样子下回到refresh方法上来:
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. 1、初始化上下文信息,替换占位符、必要参数的校验 prepareRefresh(); // Tell the subclass to refresh the internal bean factory. 2、解析类Xml、初始化BeanFactory ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 这一步主要是对初级容器的基础设计 // Prepare the bean factory for use in this context. 3、准备BeanFactory内容: prepareBeanFactory(beanFactory); // 对beanFactory容器的功能的扩展: try { // Allows post-processing of the bean factory in context subclasses. 4、扩展点加一:空实现,主要用于处理特殊Bean的后置处理器 postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. 5、spring bean容器的后置处理器 invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. 6、注册bean的后置处理器 registerBeanPostProcessors(beanFactory); // Initialize message source for this context. 7、初始化消息源 initMessageSource(); // Initialize event multicaster for this context. 8、初始化事件广播器 initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. 9、扩展点加一:空实现;主要是在实例化之前做些bean初始化扩展 onRefresh(); // Check for listener beans and register them. 10、初始化监听器 registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. 11、实例化:非兰加载Bean finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. 12、发布相应的事件通知 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... resetCommonCaches(); } } }

obtainFreshBeanFactory
让聚焦到obtainFreshBeanFactory方法,根据名称和注释简单猜测下这个方法是获取一个新的beanFactory容器。接下我们进入obtainFreshBeanFactory:
/ * Tell the subclass to refresh the internal bean factory. * @return the fresh BeanFactory instance * @see #refreshBeanFactory() * @see #getBeanFactory() */ protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { // 1、 new 一个DefaultListableBeanFactory实例,创建Spring初级容器、 // 2、设置容器是否允许循环依赖、覆盖; // 3、解析xml生成BeanDefinition对象放入beanDefinitionMap容器 refreshBeanFactory(); // 获取ConfigurableListableBeanFactory方法 return getBeanFactory(); }

obtainFreshBeanFactory只有两个方法且getBeanFactory方法只是将成员变量this.beanFactroy进行了返回,所以这方法的核心在refreshBeanFactory。
@Override public final ConfigurableListableBeanFactory getBeanFactory() { synchronized (this.beanFactoryMonitor) { if (this.beanFactory == null) { throw new IllegalStateException("BeanFactory not initialized or already closed - " + "call 'refresh' before accessing beans via the ApplicationContext"); } return this.beanFactory; } }
refreshBeanFactory
接下来我们进入refreshBeanFactory方法中看下具体逻辑:

/ * 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. */ @Override protected final void refreshBeanFactory() throws BeansException { if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { // new 一个DefaultListableBeanFactory实例,创建Spring初级容器 DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); // 定制容器参数:allowBeanDefinitionOverriding 是否允许被覆盖、allowCircularReferences 是否允许循环引用 customizeBeanFactory(beanFactory); // 开始解析并加载xml文件中的bean,将解析后的BeanDefinition放入beanDefinitionMap容器中 loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
可以看到我们上述的猜测正确的,Spring是在refreshBeanFacotry设置成员属性beanFactory,这个后面getBeanFacotry方法才可以通过成员属性获取到,再回到refreshBeanFacotry方法中。在我们进入方法的时候先是一个判断,因为第一次进去所以直接看try-catch代码块内容。
看下第一个行代码:

createBeanFactory返回一个DefaultListableBeanFactory实力对象,看到这个对象我们还是不得不提一下他的类图。
DefaultListableBeanFactory类图

在Spring中,BeanFactory是核心接口,负责实例化、配置和管理bean的生命周期。
类图结构分析
- BeanFactory
- 所有Spring容器的根接口,定义了Spring容器的基本行为。
- ListableBeanFactory
- 继承自BeanFactory,增加了列出所有bean定义的功能。
- ConfigurableBeanFactory
- 提供了对BeanFactory的额外配置能力,如设置类加载器和属性编辑器。
- SingletonBeanRegistry
- 接口,用于注册和管理单例bean。
- DefaultSingletonBeanRegistry
- SingletonBeanRegistry接口的默认实现,负责注册和解析单例bean。
- HierarchicalBeanFactory
- 允许BeanFactory形成层级结构,父工厂可以被子工厂继承。
- AbstractBeanFactory
- 抽象类,提供了BeanFactory接口的默认实现。
- AbstractAutowireCapableBeanFactory
- 抽象类,扩展了AbstractBeanFactory,增加了自动装配功能。
- ConfigurableListableBeanFactory
- 继承自ConfigurableBeanFactory和ListableBeanFactory,提供了更多配置和bean列表功能。
- DefaultListableBeanFactory
- 具体的BeanFactory实现,继承自AbstractAutowireCapableBeanFactory和ConfigurableListableBeanFactory,是Spring中最常用的bean工厂实现。
介绍完DefaultListableBeanFactory类图接着往下看。

定制容器参数:allowBeanDefinitionOverriding 是否允许被覆盖allowCircularReferences 是否允许循环引用,这两个参数后面我们会重点关注,在Bean实例化的时候,这这里咱们就留一个印象。接下来接着看
记载Xml中的BeanDefinition

今日小结
通过对 `refresh` 方法中第二个核心方法 `obtainBeanFactory` 的解读,我们了解到通过 `createBeanFactory` 创建了 Spring 的初级容器,并定义了容器的两个核心参数:是否允许循环引用和是否允许覆盖。
我们还介绍了初级容器 `DefaultListableBeanFactory` 的类图,对 Spring 初级容器的初始化和结构有了初步了解。下一篇文章中,我们将开始讨论容器第一个重要成员:BeanDefiniton。
源码整体进度
目前整体进度梳理如下:

Spring框架中容器初始化的核心步骤和概念的概述:
- 初始化时间与容器状态:这是容器启动和初始化过程中需要考虑的基础属性。
- 构造方法:容器的构造方法开始整个初始化过程。
- ClassPathXmlApplicationContext:这是一个用于从类路径下的XML配置文件中加载Spring应用上下文的特定实现。
- 初始化容器上下文环境:在容器启动时,需要设置和初始化容器的上下文环境。
- 属性值替换占位符:在配置文件中,可能包含一些占位符,需要在启动时被实际的属性值所替换。
- prepareRefresh方法:这个方法在刷新容器之前被调用,用于准备刷新操作,例如设置早期的事件多播器。
- PathMatchingResourcePatternResolver(this)实例:创建一个资源模式解析器实例,用于解析和匹配资源路径。
- 检测指定环境变量是否配置:检查环境变量是否已经设置,这可能影响资源的定位和加载。
- resolvePath解析构造方法传入文件路径的占位符$0:解析传入的文件路径,并替换其中的占位符。
- 初始化初级容器:创建
DefaultListableBeanFactory实例,这是Spring容器的基础,用于管理Bean的定义和生命周期。 - 调用obtainBeanFactory方法:这个方法用于获取或创建Bean工厂,它是容器的核心组件。
- customizeBeanFactory方法:允许对Bean工厂进行定制,例如设置是否允许循环引用或覆盖。
- loadBeanDefinitions:加载Bean定义,这可能来自XML配置文件、注解或其他源。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/4596.html