① 定位:定位资源文件(定位配置文件或扫描相关注解)
② 加载:解析配置信息
③ 注册:将Bean的信息表示解析成BeanDefinition注册到BeanDefinitionMap
ClassPathXmlApplicationContext:
- 初始化资源加载器:
AbstractApplicationContext()
// AbstractApplicationContext类
public AbstractApplicationContext() {
this.resourcePatternResolver = getResourcePatternResolver();
}
//获取一个Spring Source的加载器用于读入Spring Bean定义资源文件
protected ResourcePatternResolver getResourcePatternResolver() {
//AbstractApplicationContext继承DefaultResourceLoader,因此也是一个资源加载器
return new PathMatchingResourcePatternResolver(this);
}
-
设置资源路径:
setConfigLocations(configLocations);
-
容器初始化
AbstractApplicationContext#refresh()
:
// ClassPathXmlApplicationContext类
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException {
// IOC 1:初始化资源加载器
super(parent);
// IOC 2: 设置资源路径
setConfigLocations(configLocations);
if (refresh) {
// IOC 3:IOC容器初始化入口,重启、刷新、重置、相关组件初始化
// AbstractApplicationContext#refresh()
refresh();
}}
- 刷新bean factory:
AbstractRefreshableApplicationContext#refreshBeanFactory()
AbstractApplicationContext#refresh():
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
AbstractApplicationContext#obtainFreshBeanFactory():
refreshBeanFactory();
// AbstractRefreshableApplicationContext#refreshBeanFactory()
@Override
protected final void refreshBeanFactory() throws BeansException {
// IOC : 如果已经有容器,销毁容器中的bean,关闭容器
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// IOC :创建IOC容器
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
// 对IOC容器进行定制化,如设置启动参数,开启注解的自动装配等
customizeBeanFactory(beanFactory);
// IOC 5:开始加载BeanDefinitions.(由具体子类实现)
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
- 加载BeanDefinitions(子类实现):
AbstractXmlApplicationContext#loadBeanDefinitions()
// AbstractXmlApplicationContext#loadBeanDefinitions()
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
throws BeansException, IOException {
// IOC : 创建XmlBeanDefinitionReader,即创建Bean读取器,并通过回调设置到容器中去,容器使用该读取器读取Bean定义资源
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);
// IOC 6 : Bean读取器真正实现加载的方法
loadBeanDefinitions(beanDefinitionReader);
}
// AbstractXmlApplicationContext#loadBeanDefinitions()
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader)
throws BeansException, IOException {
// 获取资源定位
Resource[] configResources = getConfigResources();
if (configResources != null) {
// IOC 7: Xml读取器调用其父类AbstractBeanDefinitionReader读取定位的Bean定义资源
reader.loadBeanDefinitions(configResources);
}
// 获取FileSystemXmlApplicationContext构造方法中setConfigLocations方法设置的资源
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
// IOC : 遍历加载
AbstractBeanDefinitionReader#loadBeanDefinitions():
counter += loadBeanDefinitions(location);
public int loadBeanDefinitions(EncodedResource encodedResource)
throws BeanDefinitionStoreException {
try {
// IOC :将资源文件转为InputStream的IO流
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
// IOC 8 : 具体解析资源文件
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
//关闭从Resource中得到的IO流
inputStream.close();
}
}
}
- 解析资源文件,并注册到BeanDefinitionMap:
XmlBeanDefinitionReader#doLoadBeanDefinitions()
// XmlBeanDefinitionReader#doLoadBeanDefinitions()
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
// IOC : 将XML文件转换为DOM对象,解析过程由documentLoader实现
Document doc = doLoadDocument(inputSource, resource);
// IOC 9: 这里是启动对Bean定义解析的详细过程,该解析过程会用到Spring的Bean配置规则
return registerBeanDefinitions(doc, resource);
}catch(Exception ex){
// ...
}
}
//按照Spring的Bean语义要求将Bean定义资源解析并转换为容器内部数据结构
public int registerBeanDefinitions(Document doc, Resource resource)
throws BeanDefinitionStoreException {
//得到BeanDefinitionDocumentReader来对xml格式的BeanDefinition解析
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
//获得容器中注册的Bean数量
int countBefore = getRegistry().getBeanDefinitionCount();
// IOC 10:具体的解析实现过程由实现类DefaultBeanDefinitionDocumentReader完成
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
//统计解析的Bean数量
return getRegistry().getBeanDefinitionCount() - countBefore;
}
// IOC 11:解析并注册BeanDefinitions
DefaultBeanDefinitionDocumentReader#registerBeanDefinitions():
doRegisterBeanDefinitions(root);
// IOC 12 : 从根元素开始对Document元素进行解析,
DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions():
parseBeanDefinitions(root, this.delegate);
DefaultBeanDefinitionDocumentReader#parseBeanDefinitions():
parseDefaultElement(ele, delegate);
// IOC 13: 元素节点既不是导入元素,也不是别名元素,即普通的<Bean>元素
DefaultBeanDefinitionDocumentReader#parseDefaultElement():
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);}
//DefaultBeanDefinitionDocumentReader#processBeanDefinition():
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// BeanDefinitionHolder是对BeanDefinition的封装,即Bean定义的封装类
// IOC 14:将解析出的beanName和beanDefinition封装成Holder。
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// IOC 15:向Spring IOC容器注册解析得到的Bean定义
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
//在完成向Spring IOC容器注册解析得到的Bean定义之后,发送注册事件
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
AnnotationConfigApplicationContext
- 初始化注解Bean读取器和包路径扫描器:
AnnotationConfigApplicationContext()
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
// IOC 1 : 初始化注解Bean读取器和包路径扫描器
this();
// IOC 2 :直接注册beanDefinition到容器中
register(annotatedClasses);
// IOC 3 :刷新容器
refresh();
}
public AnnotationConfigApplicationContext(String... basePackages) {
this();
// IOC 2 :设置扫描包路径,将包路径下的所有Bean对象注册到容器中
scan(basePackages);
refresh();
}
- 直接注册:
register(Class<?>... annotatedClasses)
// IOC 2 :为容器注册一个要被处理的注解Bean,必须手动调用容器的refresh()方法刷新容器,触发容器对新注册的Bean的处理
public void register(Class<?>... annotatedClasses) {
Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified"); this.reader.register(annotatedClasses);
}
- 设置扫描路径:
scan(String... basePackages)
// IOC 2 :扫描指定包路径及其子包下的注解类,为了使新添加的类被处理,必须手动调用refresh()方法刷新容器
public void scan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified"); this.scanner.scan(basePackages);
}