上一篇咱们通过一个例子介绍初始化容器上下文相关内容,并通过两个示例代码看到了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、初始化BeanFactoryConfigurableListableBeanFactory 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、实例化:非兰加载BeanfinishBeanFactoryInitialization(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。
@Overridepublic 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.*/@Overrideprotected 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
进入loadBeanDefinitions方法
/*** Loads the bean definitions via an XmlBeanDefinitionReader.* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader* @see #initBeanDefinitionReader* @see #loadBeanDefinitions*/@Overrideprotected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {// Create a new XmlBeanDefinitionReader for the given BeanFactory.// 初始化XmlBeanDefinitionReaderXmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);// Configure the bean definition reader with this context's resource loading environment.// 配置BeanDefinition上下文信息beanDefinitionReader.setEnvironment(this.getEnvironment());beanDefinitionReader.setResourceLoader(this);beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));// Allow a subclass to provide custom initialization of the reader,then proceed with actually loading the bean definitions.// 看到规律了呢,Allow a subclass 基本上都是Spring 预留的扩展点,空实现,留给子类自己去自定义initBeanDefinitionReader(beanDefinitionReader);// 通过beanDefinitionReader去加载解析xml中的BeanDefinitionloadBeanDefinitions(beanDefinitionReader);}