深入理解Spring源码(开启篇)

由于平时项目中都会用到spring,但是一般都是已经配好了,我们直接使用即可,如果对源码感兴趣的童鞋可以关注下我的博客,后面会有相应的更新。这段时间有点时间,就研究了下spring的源码,打算在近期详细的归纳一下spring容器是怎么运行管理bean的整个周期。



我们简单的拿出一个spring容器初始化的代码 这里我们拿出的是基于xml的方式  基于注解的也大同小异(后续有空也可以分享)

package com.test.main;

import com.test.seivice.CarService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class test {

	public static void main(String[] args) {

		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath*:game.xml");
		CarService testDao = (CarService) applicationContext.getBean("test");
		System.out.println(testDao);
	}
}

 

AplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath*:game.xml");  简单的一行代码就实现了spring 容器初始化的整个过程,这也就是我们开始研究的入口

我们点进 ClassPathXmlApplicationContext方法里面

	public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
		this(new String[] {configLocation}, true, null);
	}

这是一个有参构造函数 我们继续点进去this方法

	public ClassPathXmlApplicationContext(
			String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {
		// 这个地方 我们传进来的parent对象为空 一路断点进去  发现parent始终为空 我们尚且不关注
		super(parent);
		// 将配置文件路径设置给AbstractRefreshableConfigApplicationContext 的configLocations的属性
		setConfigLocations(configLocations);
		// 由上面的参数传进refresh为true 下面我们就进入refresh方法 spring初始化全程
		if (refresh) {
			refresh();
		}
	}

由上面的注释 我们得知refresh()方法是贯穿spring整个初始化的方法

@Override
	public void refresh() throws BeansException, IllegalStateException {

		//加锁 防止 fresh还没结束  就又进入改方法 导致容器初始化错乱
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			//准备工作  初始化spring状态 使spring处于运行状态
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			//这一步主要作用是将配置文件定义解析成beanDefine 注册到beanFactory中
			//但是这里的bean并没有初始化出来 只是提取配置信息 定义相关的属性
			//将这些信息保存到beanDefineMap中(beanName->beanDefine)对应的map
			//我们将深入进去 仔细看看源码
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			//设置BeanFactory的类加载器,添加几个BeanPostProcessor 手动注册几个特殊的bean
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				//重要
				postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
				// 重要 在spring的环境中执行已经被注册的factory processors
				// 设置执行自定义的ProcessBeanFactory 和 spring内部的定义的
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				// 初始化所有的singleton beans 到目前为止 我们已经完成了beanFactory的创建
				// 如果没有设置懒加载 spring会为我们初始化所有的bean
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
                } catch (BeansException 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();
			}
		}
	}

后面这段时间我们将逐个分析refresh()方法中的12个方法,这个方法也是注解或者xml解析必须经过的方法。

建议读者下载spring源码  这样方便于注释 断点调式,下面一章我们来介绍下 prepareRefresh()方法

上一篇:android – 按下后退按钮时调用方法


下一篇:WinForm之 AcceptButton和CancelButton