Spring对于程序员说来讲都不陌生;做为一个强大的开源技术,帮助咱们可以更好的进行项目的开发与维护。
java
上次在Spring的启动过程文章中对Spring的启动过程作了一个较为详细的说明和分析。那么在实际的过程当中,Spring的启动实际上就是Spring容器的初始化过程。本文将从源码的角度结合本身断点执行过程当中保留的现场来分析一下容器的刷新过程(主要分析前几个方法,后面几个会分开来讲)。程序员
Spring的启动是经过ContextLoaderListener来进行的,在ContextLoaderListener中经过委托父类ContextLoader的initWebApplicationContext来完成具体的初始化过程。具体的启动过程能够看下以前的那篇文章。web
在initWebApplicationContext方法是用来建立容器的,核心代码以下:spring
refresh()方法主要为IoC容器Bean的生命周期管理提供条件,Spring IoC容器载入Bean定义资源文件从其子类容器的refreshBeanFactory()方法启动,因此整个refresh()中“ConfigurableListableBeanFactory beanFactory =obtainFreshBeanFactory();”这句之后代码的都是注册容器的信息源和生命周期事件,载入过程就是从这句代码启动。 AbstractApplicationContext的obtainFreshBeanFactory()方法调用子类容器的refreshBeanFactory()方法,启动容器载入Bean定义资源文件的过程。 refresh()方法的做用是:在建立IoC容器前,若是已经有容器存在,则须要把已有的容器销毁和关闭,以保证在refresh以后使用的是新创建起来的IoC容器。refresh的做用相似于对IoC容器的重启,在新创建好的容器中对容器进行初始化,对Bean定义资源进行载入。 和refreshBeanFactory方法相似,载入Bean定义的方法loadBeanDefinitions也使用了委派模式,在AbstractRefreshableApplicationContext类中只定义了抽象方法,具体的实现调用子类容器中的方法实现。apache
//通知子类去刷新内部bean 工厂tomcat
此实现执行该上下文的底层bean工厂的实际刷新,关闭之前的bean工厂(若是有的话),并为上下文生命周期的下一阶段初始化一个新的bean工厂。
bash
customizeBeanFactory(DefaultListableBeanFactory beanFactory)websocket
/**
//经过当前上下文来自定义内部bean工厂<br>
* Customize the internal bean factory used by this context.
* Called for each {@link #refresh()} attempt.
* <p>The default implementation applies this context's * {@linkplain #setAllowBeanDefinitionOverriding "allowBeanDefinitionOverriding"} * and {@linkplain #setAllowCircularReferences "allowCircularReferences"} settings, * if specified. Can be overridden in subclasses to customize any of * {@link DefaultListableBeanFactory}'s settings.
* @param beanFactory the newly created bean factory for this context
* @see DefaultListableBeanFactory#setAllowBeanDefinitionOverriding
* @see DefaultListableBeanFactory#setAllowCircularReferences
* @see DefaultListableBeanFactory#setAllowRawInjectionDespiteWrapping
* @see DefaultListableBeanFactory#setAllowEagerClassLoading
*/
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
if (this.allowBeanDefinitionOverriding != null) {
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.allowCircularReferences != null) {
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
}
}
复制代码
XmlWebApplicationContext类中loadBeanDefinitions(beanFactory)session
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's // resource loading environment. beanDefinitionReader.setEnvironment(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. initBeanDefinitionReader(beanDefinitionReader); loadBeanDefinitions(beanDefinitionReader); } 复制代码
AbstractApplicationContext调用loadBeanDefinitions(DefaultListableBeanFactory beanFactory) ,此方法根据首先建立XmlBeanDefinitionReader对象,而后配置该对象的上下文和资源加载环境,同时调用子类实现的initBeanDefinitionReader对XmlBeanDefinitionReader进行个性化配置,最近后入到initBeanDefinitionReader(beanDefinitionReader)的调用:app
装载bean定义经过XmlBeanDefinitionReader。
// Create a new XmlBeanDefinitionReader for the given BeanFactory. 经过给定的bean工厂建立一个新的XmlBeanDefinitionReader
1.XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
2.使用上下文的资源加载环境配置bean定义读取器。
beanDefinitionReader.setEnvironment(getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
3.容许子类提供reader的自定义初始化,而后继续实际加载bean定义。
//经过制定的XmlBeanDefinitionReader来载入beandefinitionReader
initBeanDefinitionReader(beanDefinitionReader)
// 经过制定的XmlBeanDefinitionReader来载入bean definitions
loadBeanDefinitions(beanDefinitionReader)
复制代码
AbstractApplicationContext调用loadBeanDefinitions(beanDefinitionReader),这个方法是取得资源或资源路径而后经过传入的reader去加载BeanDefinitions。
目前使用Spring的配置都是基于XML的,所以使用XmlBeanDefinitionReader 中的loadBeanDefinitions方法。
配置工厂的标准上下文特性,如上下文的类装载器和后处理器。
经过断点来看下当前的beanFactory
注册web特性的全局域
1).registerWebApplicationScopes
注册web特性 环境bean(“contextparameters”、“ContextAttribute”)与给定的WebApplicationContext使用BeanFactory。
1.servletContext
BeanDefinitionRegistryPostProcessor实例化:标准BeanFactoryPostProcessor的扩展,BeanFactoryPostProcessor的做用是用来进一步定义注册的BeanDefinition,IoC容器本质就是Bean管理,因此BeanFactoryPostProcessor自己也是Bean,要对BeanFactoryPostProcessor的BeanDefinition进一步定义就经过BeanDefinitionRegistryPostProcessor进行注册,BeanDefinitionRegistryPostProcessor及其子类是Ioc容器最实例化的一类Bean。它们在ConfigurableApplicationContext(ApplicationContext子接口)实现类调用refresh()方法调用invokeBeanFactoryPostProcessors(beanFactory);方法时就被实例化。
OK,今天关于这部分的分析就到此结束了,后面的过程会在下一篇Spring系列文章中继续来说refresh中的过程。
祝你们平安夜快乐....
若是您对系列文章有任何意见,能够给我留言,感谢你们。
下面是一个接苹果的姿式,呼呼呼.....