spring源码解读(二)spring容器如何加载xml配置文件到容器中

本文深入探讨了Spring如何将XML配置文件加载到容器中,从ClassPathXmlApplicationContext开始,详细跟踪了从refresh()方法到loadBeanDefinitions()的整个过程,解释了bean定义的解析和注册。
摘要由CSDN通过智能技术生成

上一篇介绍了如何下载spring源码,编译,及修改源码+注解的使用

spring容器的基本使用及xml配置属性的说明;
这篇文章来介绍下spring容器时如何加载解析xml配置到spring容器中的

首先从测试代码中看到

package com.wsj.spring;

import com.wsj.spring.bean.LookUpSayHello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {

    public static void main(String[] args) {
        ApplicationContext app=new ClassPathXmlApplicationContext("test.xml");
        LookUpSayHello bean = app.getBean(LookUpSayHello.class);
        bean.sayHello();
    }
}

使用ClassPathXmlApplicationContext加载xml文件,下面跟进去,最终调到这个构造方法 

/**
	 * Create a new ClassPathXmlApplicationContext with the given parent,
	 * loading the definitions from the given XML files.
	 * @param configLocations array of resource locations
	 * @param refresh whether to automatically refresh the context,
	 * loading all bean definitions and creating all singletons.
	 * Alternatively, call refresh manually after further configuring the context.
	 * @param parent the parent context
	 * @throws BeansException if context creation failed
	 * @see #refresh()
	 */
	public ClassPathXmlApplicationContext(
			String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {

		super(parent);
		//这里可以根据不同的子类实现
		// 根据提供的路径,处理成配置文件数组(以分号、逗号、空格、tab、换行符分割)
		setConfigLocations(configLocations);
		if (refresh) {
			/**
			 * 这里简单说下为什么是 refresh(),而不是 init() 这种名字的方法。
			 * 因为 ApplicationContext 建立起来以后,其实我们是可以通过调用 refresh() 这个方法重建的,这样会将原来的 ApplicationContext 销毁,
			 * 然后再重新执行一次初始化操作。
			 */
			refresh();// 核心方法
		}
	}

点击进入refresh()方法,会看到跳转到父类(其实时爷爷的爷爷类)

AbstractApplicationContext中,
@Override
	public void refresh() throws BeansException, IllegalStateException {
		// 来个锁,不然 refresh() 还没结束,你又来个启动或销毁容器的操作,那不就乱套了嘛
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			// 准备工作,记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			// 这步比较关键,这步完成后,配置文件就会解析成一个个Bean定义(BeanDefinition),注册到 BeanFactory 中,
			// 当然,这里说的 Bean 还没有初始化,只是配置信息都提取出来了,
			// 注册也只是将这些信息都保存到了注册中心(说到底核心是一个 beanName-> beanDefinition 的 map)
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);
			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);
				//完成BeanFactoryPostProcessors 和BeanDefinitionRegistryPostProcessor的实例化,执行相应的postProcessor方法
				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);
				//实例化所有beanPostProcessors实例到容器中
				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);
				//国际化代码
				// Initialize message source for this context.
				initMessageSource();
				//spring事件代码
				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();
				//可以自定义的onRefresh()
				// Initialize other special beans in specific context subclasses.
				onRefresh();
				//事件的监听
				// Check for listener beans and register them.
				registerListeners();
				//初始化单实例bean。spring ioc的核心代码入口
				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);
				//完成容器的刷新
				// Last step: publish corresponding event.
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabl
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值