做会员体系的网站,重庆在线高校平台登录,网页网站建设的ppt,青岛网站建设免费上一篇咱们通过一个例子介绍初始化容器上下文相关内容#xff0c;并通过两个示例代码看到了Spring在设计阶段为我预留的扩展点#xff0c;和我们应该如何利用这两个扩展点在Spring初始化容器上下文阶段为我们提供服务。这一篇咱们接着往下看。
老这样子下回到refresh方法上来…上一篇咱们通过一个例子介绍初始化容器上下文相关内容并通过两个示例代码看到了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 Springs 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 contexts underlying* bean factory, shutting down the previous bean factory (if any) and* initializing a fresh bean factory for the next phase of the contexts 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 contexts 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);}