读spring源码__IOC
上一张中提到的initWebApplicationContext方法中configureAndRefreshWebApplicationContext方法是用来进行WebApplicationContext的配置工作,其中包括把servletContext和Spring容器关联起来,以及将配置文件(applicationContext.xml)加入到容器中。将配置文件加载,容器初始化结束后,下面看看ContextLoader的configureAndRefreshWebApplicationContext方法的实现:
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
// The application context id is still set to its original default value
// -> assign a more useful id based on available information
String idParam = sc.getInitParameter(CONTEXT_ID_PARAM);
if (idParam != null) {
wac.setId(idParam);//将contextId的值设置到容器中
}
else {
// Generate default id...
if (sc.getMajorVersion() == 2 && sc.getMinorVersion() < 5) {
// Servlet <= 2.4: resort to name specified in web.xml, if any.
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
ObjectUtils.getDisplayString(sc.getServletContextName()));
}
else {
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
ObjectUtils.getDisplayString(sc.getContextPath()));
}
}
}
wac.setServletContext(sc);//将上下文环境servletcontext设置到容器中
String initParameter = sc.getInitParameter(CONFIG_LOCATION_PARAM);
if (initParameter != null) {
wac.setConfigLocation(initParameter);//将xml配置文件的路径设置到容器中
}
customizeContext(sc, wac);
wac.refresh();//在这个方法中完成了配置文件的加载
}
wac.refresh()方法完成了bean的加载,存储到bean缓冲池中,创建了beanFactory,注册了监听器等。
wac.refresh()的实现如下:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识
prepareRefresh();//告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从子类的refreshBeanFactory()方法启动
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();//为BeanFactory配置容器特性,例如类加载器、事件处理器等
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// 为容器的某些子类指定特殊的BeanPost事件处理器
postProcessBeanFactory(beanFactory);
// 调用所有注册的BeanFactoryPostProcessor的Bean
invokeBeanFactoryPostProcessors(beanFactory);
// 为BeanFactory注册BeanPost事件处理器.BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件
registerBeanPostProcessors(beanFactory);
// 初始化信息源,和国际化相关.
initMessageSource();
// 初始化容器事件传播器.
initApplicationEventMulticaster();
// 调用子类的某些特殊Bean初始化方法
onRefresh();
// 为事件传播器注册事件监听器.
registerListeners();
// 初始化所有剩余的单态Bean.
finishBeanFactoryInitialization(beanFactory);
// 初始化容器的生命周期事件处理器,并发布容器的生命周期事件
finishRefresh();
}
catch (BeansException ex) {
// //销毁以创建的单态Bean
destroyBeans();
// 取消refresh操作,重置容器的同步标识.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
}
}
这个方法中的obtainFreshBeanFactory方法完成了beanfactory的创建,Spring将配置文件的信息放到容器的Bean定义注册表中(即beanDefinationRegistry),但此时bean还没有初始化。实现如下:
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
跟进refreshBeanFactory()方法:
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();//销毁单例对象
closeBeanFactory();//关闭beanFactory
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();//创建BeanFactory
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);//通过配置文件加载bean
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
进入loadBeanDefinitions方法:
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(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.
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}
直接进入loadBeanDefinitions(beanDefinitionReader)方法中,最终执行下面这个loadBeanDefinitions方法。
public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
}
if (resourceLoader instanceof ResourcePatternResolver) {
// Resource pattern matching available.
try {
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
int loadCount = loadBeanDefinitions(resources);//在这里加载资源配置文件,返回获取的资源个数
if (actualResources != null) {
for (Resource resource : resources) {
actualResources.add(resource);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
}
return loadCount;
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"Could not resolve bean definition resource pattern [" + location + "]", ex);
}
}
else {
// Can only load single resources by absolute URL.
Resource resource = resourceLoader.getResource(location);
int loadCount = loadBeanDefinitions(resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
}
return loadCount;
}
}
继续进入int loadCount = loadBeanDefinitions(resource);中
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
Assert.notNull(resources, "Resource array must not be null");
int counter = 0;
for (Resource resource : resources) {
counter += loadBeanDefinitions(resource);
}
return counter;
}
返回bean的个数,resource是返回的资源,通过resource读取配置文件的内容
以上都只是将beanDefination信息存入Bean定义注册表中(即beanDefinationRegistry),并没有将bean初始化。而初始化的工作是由InstantiationStrategy实例化,由beanWrapper完成属性填充。
1.2初始化beanfactory
进入AbstractRefreshableApplicationContext.java类的refreshBeanFactory方法中
在这个方法中,先判断是否有容器存在,如果已经有了一个beanfactory存在,先销毁bean,再关闭容器。try中的语句 {
- 创建beanfactory
- 设置序列化id
- 定制化beanFactory
加载beandefinitions
}
BeanFactory类体系结构
BeanFactory 接口位于类结构树的顶端, 它最主要的方法就是getBean(StringbeanName),该方法从容器中返回特定名称的Bean,BeanFactory 的功能通过其他的接口得到不断扩展。ListableBeanFactory:该接口定义了访问容器中Bean 基本信息的若干方法,如查看Bean 的个数、获取某一类型Bean 的配置名、查看容器中是否包括某一Bean 等方法;
HierarchicalBeanFactory:父子级联IoC 容器的接口,子容器可以通过接口方法访问父容器;
ConfigurableBeanFactory:是一个重要的接口,增强了IoC 容器的可定制性,它定义了设置类装载器、属性编辑器、容器初始化后置处理器等方法;
AutowireCapableBeanFactory:定义了将容器中的Bean 按某种规则(如按名字匹配、按类型匹配等)进行自动装配的方法;
SingletonBeanRegistry:定义了允许在运行期间向容器注册单实例Bean 的方法;
BeanDefinitionRegistry:spring 配置文件中每一个节点元素在Spring 容器里都通过一个BeanDefinition 对象表示,它描述了Bean 的配置信息。而BeanDefinitionRegistry 接口提供了向容器手工注册BeanDefinition 对象的方法。