Spring框架九、Spring IOC启动流程源码分析一

准备工作

public class MyTest {
    @Test
    public void test01() throws FileNotFoundException {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application_context.xml");
        BookService bookService = context.getBean("bookService", BookService.class);
        System.out.println(bookService);
    }
}

一、new ClassPathXmlApplicationContext(“application_context.xml”)

看一下ClassPathXmlApplicationContext源码很简单


public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
  //配置文件数组,这里存储的就是我们的外部资源"application_context.xml"转化成Resource对象的数组
  private Resource[] configResources;

  // 指定ApplicationContext的父容器
  public ClassPathXmlApplicationContext(ApplicationContext parent) {
    super(parent);
  }
  
  public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
      throws BeansException {

    super(parent);
    // 根据提供的路径,处理成配置文件数组(以分号、逗号、空格、tab、换行符分割)
    setConfigLocations(configLocations);
    
    if (refresh) {
      refresh();
    }
  }
}

可以看到,只有setConfigLocations和refresh两个方法,没有看到具体的实现。我们一步一步来,先看一下super(parent)做了什么

二、super(parent)

初始化父类,AbstractXmlApplicationContext---->AbstractRefreshableConfigApplicationContext---->AbstractRefreshableApplicationContext---->AbstractApplicationContext。

最后到达了AbstractApplicationContext抽象类里面:AbstractApplicationContext.java部分源码

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
	/**
	 * 初始化资源加载器,ResourcePatternResolver extends ResourceLoader。
	 */
	public AbstractApplicationContext() {
		this.resourcePatternResolver = getResourcePatternResolver();
	}
	/**
	 * 创建资源加载器
	 * PathMatchingResourcePatternResolver implements ResourcePatternResolver
	 * ResourcePatternResolver extends ResourceLoader
	 * PathMatchingResourcePatternResolver是ResourcePatternResolver资源加载器接口的具体实现
	 */
	protected ResourcePatternResolver getResourcePatternResolver() {
		return new PathMatchingResourcePatternResolver(this);
	}
	
	/**
	 * 从这里进来
	 */
	public AbstractApplicationContext(@Nullable ApplicationContext parent) {
		this();
		setParent(parent);
	}
	/**
	 * 设置一些上下文环境以及一些系统资源
	 */
	@Override
	public void setParent(@Nullable ApplicationContext parent) {
		this.parent = parent;
		if (parent != null) {
			Environment parentEnvironment = parent.getEnvironment();
			if (parentEnvironment instanceof ConfigurableEnvironment) {
				getEnvironment().merge((ConfigurableEnvironment) parentEnvironment);
			}
		}
	}
}

PathMatchingResourcePatternResolver 这个实现类,就是用来解释不同路径资源的,比如你传入的资源路径有可能是一个常规的 url ,又或者有可能是以 classpath* 前缀,都交给它处理。

接下来回过头来看setConfigLocations(configLocations)

三、setConfigLocations(configLocations)

setConfigLocations方法的主要工作有两个:创建环境对象ConfigurableEnvironment和处理ClassPathXmlApplicationContext传入的字符串中的占位符

	public void setConfigLocations(@Nullable String... locations) {
		if (locations != null) {
			Assert.noNullElements(locations, "Config locations must not be null");
			this.configLocations = new String[locations.length];
			for (int i = 0; i < locations.length; i++) {
				this.configLocations[i] = resolvePath(locations[i]).trim();
			}
		}
		else {
			this.configLocations = null;
		}
	}

	/**
	 * 解析给定的资源路径,必要时用相应的环境属性值替换占位符,应用于资源路径配置。
	 */
	protected String resolvePath(String path) {
		return getEnvironment().resolveRequiredPlaceholders(path);
	}

1、创建环境

	@Override
	public ConfigurableEnvironment getEnvironment() {
		if (this.environment == null) {
			this.environment = createEnvironment();
		}
		return this.environment;
	}
	protected ConfigurableEnvironment createEnvironment() {
		return new StandardEnvironment();
	}
public class StandardEnvironment extends AbstractEnvironment {

	/** System environment property source name: {@value}. */
	public static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME = "systemEnvironment";

	/** JVM system properties property source name: {@value}. */
	public static final String SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME = "systemProperties";


	/**
	 * 往资源列表中添加Java进程中的变量和系统的环境变量
	 */
	@Override
	protected void customizePropertySources(MutablePropertySources propertySources) {
		propertySources.addLast(
				new PropertiesPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
		propertySources.addLast(
				new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
	}

}

2、处理占位符

getEnvironment().resolveRequiredPlaceholders(path)最终会调到:PropertyPlaceholderHelper类的parseStringValue()方法,这个方法主要就是解析所有使用${}方式的占位符。

四、refresh()核心函数

调用父类AbstractApplicationContext的refresh()方法如下:

/**
	 * refresh方法主要为IOC容器Bean的生命周期管理提供条件,在获取了BeanFactory之后都是在向该容器注册信息源和生命周期事件
	 * 在创建IOC容器前,如果已经有容器存在,需要把已有的容器销毁和关闭,以保证在refresh()方法之后
	 * 使用的是新创建的IOC容器。
	 *
	 * @throws BeansException
	 * @throws IllegalStateException
	 */
	@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			// 调用容器准备刷新的方法,获取容器的当前时间,同时给容器设置同步标识
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			// 获得beanFactory
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			// beanFactory的预准备工作,对beanfactory配置容器特性,例如类加载器、事件处理器等
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				//beanFactory准备工作完成之后要进行的后置处理工作,留给子类扩展使用
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				//执行BeanFactory的后置处理器,在BeanFactory标准初始化之后执行的,调用所有注册的BeanFactoryPostProcessor的Bean
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				// 为BeanFactory注册Post事件处理器,BeanPostProcessor是Bean的后置处理器,用于监听容器触发的事件
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				//初始化MessageSource信息源,即国际化处理、消息绑定、消息解析
				initMessageSource();

				// Initialize event multicaster for this context.
				//初始化容器事件广播器,并放入applicationEventMulticaster bean中
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				//留给子类来初始化其他的bean
				onRefresh();

				// Check for listener beans and register them.
				//在所有注册的bean中查找ApplicationListener,为事件广播器注册事件监听器
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				//初始化所有剩下的单实例bean
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				//完成刷新过程,初始化容器的生命周期事件处理器,并发布容器的生命周期事件
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				// 销毁已经创建的Bean
				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();
			}
		}
	}

1、prepareRefresh()

做一些准备工作,记录容器的启动时间、标记“已启动”状态、检查环境变量等。其中检查环境变量为核心方法,简单来说就是如果存在环境变量的value为空的时候就抛异常,然后停止启动Spring。


  protected void prepareRefresh() {
      this.startupDate = System.currentTimeMillis();
      this.closed.set(false);
      this.active.set(true);

      if (logger.isInfoEnabled()) {
         logger.info("Refreshing " + this);
      }

      // 初始化加载配置文件方法,并没有具体实现,一个留给用户的扩展点
      initPropertySources();

      // 检查环境变量
      getEnvironment().validateRequiredProperties();

      this.earlyApplicationEvents = new LinkedHashSet<>();
   }
	public void validateRequiredProperties() {
		MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException();
		for (String key : this.requiredProperties) {
			if (this.getProperty(key) == null) {
				ex.addMissingRequiredProperty(key);
			}
		}
		if (!ex.getMissingRequiredProperties().isEmpty()) {
			throw ex;
		}
	}

基于这个特性我们可以做一些扩展,提前在集合requiredProperties中放入我们这个项目必须存在的一些环境变量。假说我们的生产环境数据库地址、用户名和密码都是使用环境变量的方式注入进去来代替测试环境的配置,那么就可以在这里添加这个校验,在程序刚启动的时候就能发现问题。

2、obtainFreshBeanFactory()

此方法主要是创建BeanFactory并把从资源文件解析出来的 BeanDefinitions 注册到此 BeanFactory 中。

1>、AbstractApplicationContext.java返回创建的BeanFactory
	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		//核心
		refreshBeanFactory();
		//返回刚刚创建的 BeanFactory
		return getBeanFactory();
	}
2>、调用AbstractRefreshableApplicationContext.java中的refreshBeanFactory()方法创建BeanFactory并且调用loadBeanDefinitions()方法。
	protected final void refreshBeanFactory() throws BeansException {
		// 判断是否有BeanFactory,如果已经有容器,则销毁容器中的Bean,关闭容器
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			//创建DefaultListableBeanFactory,IOC容器
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			//设置序列化id
			beanFactory.setSerializationId(getId());
			//定制beanfactory,设置相关属性,如设置启动参数、开启注解的自动装配等
			customizeBeanFactory(beanFactory);
			//调用载入Bean定义的方法,此类只是定义了抽象方法,通过子类容器实现
			loadBeanDefinitions(beanFactory);
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}
3>、调用AbstractXmlApplicationContext.java类的loadBeanDefinitions()方法,这个方法会根据配置,加载各个 Bean,然后放到创建的DefaultListableBeanFactory的beanDefinitionMap中。
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// Create a new XmlBeanDefinitionReader for the given BeanFactory.
		// 创建XmlBeanDefinitionReader,即创建Bean读取器
		// 并通过回调设置到容器中,容器使用该读取器读取Bean配置资源
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

		// Configure the bean definition reader with this context's
		// resource loading environment.
		// 为Bean读取器设置Spring资源加载器
		beanDefinitionReader.setEnvironment(this.getEnvironment());
		beanDefinitionReader.setResourceLoader(this);
		// 为Bean读取器设置SAX xml解析器
		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

		// Allow a subclass to provide custom initialization of the reader,
		// then proceed with actually loading the bean definitions.
		// 当Bean读取器读取Bean定义的xml资源文件时,启用xml的校验机制
		initBeanDefinitionReader(beanDefinitionReader);
		// Bean读取器真正实现加载的方法
		loadBeanDefinitions(beanDefinitionReader);
	}

	/**
	 * xml Bean读取器加载Bean配置资源
	 */
	protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		//获取Bean配置资源的定位
		Resource[] configResources = getConfigResources();
		if (configResources != null) {
			//xml Bean读取器调用其父类abstractBeanDefinitionReader读取定义的Bean配置资源
			reader.loadBeanDefinitions(configResources);
		}
		//如果子类中获取的Bean配置资源定位为空,则获取ClassPathXmlApplicationContext构造方法中setConfigLocations方法设置的资源
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			//xml Bean读取器调用其父类AbstractBeanDefinitionReader获取定位的Bean配置资源
			reader.loadBeanDefinitions(configLocations);
		}
	}
4>、接着调用XmlBeanDefinitionReader.java方法的loadBeanDefinitions(Resource resource)–>loadBeanDefinitions(EncodedResource encodedResource)–>doLoadBeanDefinitions(InputSource inputSource, Resource resource)–>registerBeanDefinitions(Document doc, Resource resource)
	/**
	 * XmlBeanDefinitionReader加载资源的入口方法
	 */
	@Override
	public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
		// 将读入的XML资源进行特殊编码处理
		return loadBeanDefinitions(new EncodedResource(resource));
	}

	/**
	 * 载入XML形式Bean配置信息方法
	 */
	public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
		Assert.notNull(encodedResource, "EncodedResource must not be null");
		if (logger.isTraceEnabled()) {
			logger.trace("Loading XML bean definitions from " + encodedResource);
		}

		Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
		if (currentResources == null) {
			currentResources = new HashSet<>(4);
			this.resourcesCurrentlyBeingLoaded.set(currentResources);
		}
		if (!currentResources.add(encodedResource)) {
			throw new BeanDefinitionStoreException(
					"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
		}
		try {
			// 将资源文件转为InputStream的IO流
			InputStream inputStream = encodedResource.getResource().getInputStream();
			try {
				// 从InputStream中得到XML的解析源
				InputSource inputSource = new InputSource(inputStream);
				if (encodedResource.getEncoding() != null) {
					inputSource.setEncoding(encodedResource.getEncoding());
				}
				// 具体读取过程
				return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
			}
			finally {
				// 关闭从Resource中得到的IO流
				inputStream.close();
			}
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException(
					"IOException parsing XML document from " + encodedResource.getResource(), ex);
		}
		finally {
			currentResources.remove(encodedResource);
			if (currentResources.isEmpty()) {
				this.resourcesCurrentlyBeingLoaded.remove();
			}
		}
	}

	/**
	 * 从特定XML文件中实际载入Bean配置资源的方法
	 */
	protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {

		try {
			// 将XML文件转换为DOM对象,解析过程由documentLoader方法实现
			Document doc = doLoadDocument(inputSource, resource);
			// 启动对Bean定义解析的详细过程,该解析过程会用到Spring的Bean配置规则
			int count = registerBeanDefinitions(doc, resource);
			if (logger.isDebugEnabled()) {
				logger.debug("Loaded " + count + " bean definitions from " + resource);
			}
			return count;
		}
		catch (BeanDefinitionStoreException ex) {
			throw ex;
		}
		catch (SAXParseException ex) {
			throw new XmlBeanDefinitionStoreException(resource.getDescription(),
					"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
		}
		catch (SAXException ex) {
			throw new XmlBeanDefinitionStoreException(resource.getDescription(),
					"XML document from " + resource + " is invalid", ex);
		}
		catch (ParserConfigurationException ex) {
			throw new BeanDefinitionStoreException(resource.getDescription(),
					"Parser configuration exception parsing XML from " + resource, ex);
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException(resource.getDescription(),
					"IOException parsing XML document from " + resource, ex);
		}
		catch (Throwable ex) {
			throw new BeanDefinitionStoreException(resource.getDescription(),
					"Unexpected exception parsing XML document from " + resource, ex);
		}
	}

	public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		//得到BeanDefinitionDocumentReader来对XML格式的BeanDefinition进行解析
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		//获取容器中注册的Bean数量
		int countBefore = getRegistry().getBeanDefinitionCount();
		//加载及注册bean,具体的解析过程由实现类DefaultBeanDefinitionDocumentReader完成
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		//记录本次加载的BeanDefinition个数
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}
5>、接着调用XmlBeanDefinitionReader.java方法的
	public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		//得到BeanDefinitionDocumentReader来对XML格式的BeanDefinition进行解析
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		//获取容器中注册的Bean数量
		int countBefore = getRegistry().getBeanDefinitionCount();
		//加载及注册bean,具体的解析过程由实现类DefaultBeanDefinitionDocumentReader完成
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		//记录本次加载的BeanDefinition个数
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}
6>、继续调用DefaultBeanDefinitionDocumentReader.java的如下方法进行解析
	public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		// 获得XML描述符
		this.readerContext = readerContext;
		//获取document的根元素
		doRegisterBeanDefinitions(doc.getDocumentElement());
	}

	protected void doRegisterBeanDefinitions(Element root) {

		// 具体的解析过程由BeanDefinitionParserDelegate实现,其中定义了Spring Bean定义XML文件的各种元素
		BeanDefinitionParserDelegate parent = this.delegate;
		this.delegate = createDelegate(getReaderContext(), root, parent);

		if (this.delegate.isDefaultNamespace(root)) {
			//处理profile属性
			String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
			if (StringUtils.hasText(profileSpec)) {
				String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
						profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
				// We cannot use Profiles.of(...) since profile expressions are not supported
				// in XML config. See SPR-12458 for details.
				if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
					if (logger.isDebugEnabled()) {
						logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
								"] not matching: " + getReaderContext().getResource());
					}
					return;
				}
			}
		}

		//在解析Bean定义之前,进行自定义解析,增强解析过程的可扩展性
		preProcessXml(root);
		//从文档的根元素开始进行Bean定义的文档对象的解析
		parseBeanDefinitions(root, this.delegate);
		//在解析Bean定义之后,进行自定义解析,增加解析过程的可扩展性
		postProcessXml(root);

		this.delegate = parent;
	}

preProcessXml和postProcessXml着两个办法是留给我们实现DefaultBeanDefinitionDocumentReader方法后自定义实现的

	/**
	 * 使用Spring的Bean规则从文档的根元素开始Bean定义的文档对象的解析
	 */
	protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		//Bean定义的文档对象使用了Spring默认的XML命名空间
		if (delegate.isDefaultNamespace(root)) {
			//获取Bean定义的文档对象根元素的所有子节点
			NodeList nl = root.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				//获取的文档节点是XML元素节点
				if (node instanceof Element) {
					Element ele = (Element) node;
					//对bean的处理
					if (delegate.isDefaultNamespace(ele)) {
						//使用Spring的Bean规则解析元素节点
						parseDefaultElement(ele, delegate);
					} else {
						//如果没有使用Spring默认的XML命名空间,则使用用户自定义的解析规则解析元素节点
						delegate.parseCustomElement(ele);
					}
				}
			}
		} else {
			//文档的根节点没有使用Spring默认的命名空间,使用自定义的解析规则解析文档的根节点
			delegate.parseCustomElement(root);
		}
	}

	//使用Spring的Bean规则解析文档元素节点
	private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
		//对import标签的处理
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			importBeanDefinitionResource(ele);
		}
		//对alias标签的处理
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			processAliasRegistration(ele);
		}
		//对bean标签的处理
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			processBeanDefinition(ele, delegate);
		}
		//对beans标签的处理
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// recurse
			doRegisterBeanDefinitions(ele);
		}
	}

	/**
	 * 解析import导入元素,从给定的导入路径加载Bean资源到Spring IOC容器中
	 */
	protected void importBeanDefinitionResource(Element ele) {
		//获取给定的导入元素的location属性
		String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
		//如果导入元素的location属性为空,则没有导入任何资源,直接返回
		if (!StringUtils.hasText(location)) {
			getReaderContext().error("Resource location must not be empty", ele);
			return;
		}

		// Resolve system properties: e.g. "${user.dir}"
		//使用系统变量值解析location属性值
		location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);

		Set<Resource> actualResources = new LinkedHashSet<>(4);

		// Discover whether the location is an absolute or relative URI
		//标识给定的导入元素的location属性值是否是绝对路径
		boolean absoluteLocation = false;
		try {
			absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
		} catch (URISyntaxException ex) {
			// cannot convert to an URI, considering the location relative
			// unless it is the well-known Spring prefix "classpath*:"
		}

		// Absolute or relative?
		// 给定的导入元素的location属性值是绝对路径
		if (absoluteLocation) {
			try {
				//使用资源读入器加载给定路径的Bean资源
				int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
				if (logger.isTraceEnabled()) {
					logger.trace("Imported " + importCount + " bean definitions from URL location [" + location + "]");
				}
			} catch (BeanDefinitionStoreException ex) {
				getReaderContext().error(
						"Failed to import bean definitions from URL location [" + location + "]", ele, ex);
			}
		} else {
			// No URL -> considering resource location as relative to the current file.
			// 给定的导入元素的location属性值是相对路径
			try {
				int importCount;
				//将给定导入元素的location封装为相对路径
				Resource relativeResource = getReaderContext().getResource().createRelative(location);
				if (relativeResource.exists()) {
					//使用资源读入器加载Bean资源
					importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
					actualResources.add(relativeResource);
				}
				//封装的相对路径资源不存在
				else {
					//获取Spring IOC容器资源读入器的基本路径
					String baseLocation = getReaderContext().getResource().getURL().toString();
					//根据Spring IOC容器资源读入器的基本路径加载给定导入路径的资源
					importCount = getReaderContext().getReader().loadBeanDefinitions(
							StringUtils.applyRelativePath(baseLocation, location), actualResources);
				}
				if (logger.isTraceEnabled()) {
					logger.trace("Imported " + importCount + " bean definitions from relative location [" + location + "]");
				}
			} catch (IOException ex) {
				getReaderContext().error("Failed to resolve current resource location", ele, ex);
			} catch (BeanDefinitionStoreException ex) {
				getReaderContext().error(
						"Failed to import bean definitions from relative location [" + location + "]", ele, ex);
			}
		}
		Resource[] actResArray = actualResources.toArray(new Resource[0]);
		//在解析完import元素之后,发送容器导入其他资源处理完成事件
		getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
	}

	/**
	 * 解析alias别名元素,为Bean向IOC容器注册别名
	 */
	protected void processAliasRegistration(Element ele) {
		//获取alias别名元素中name的属性值
		String name = ele.getAttribute(NAME_ATTRIBUTE);
		//获取alias别名元素中alias的属性值
		String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
		boolean valid = true;
		//别名元素的name属性值为空
		if (!StringUtils.hasText(name)) {
			getReaderContext().error("Name must not be empty", ele);
			valid = false;
		}
		//alias别名元素的alias属性值为空
		if (!StringUtils.hasText(alias)) {
			getReaderContext().error("Alias must not be empty", ele);
			valid = false;
		}
		if (valid) {
			try {
				//向容器的资源读入器注册别名
				getReaderContext().getRegistry().registerAlias(name, alias);
			} catch (Exception ex) {
				getReaderContext().error("Failed to register alias '" + alias +
						"' for bean with name '" + name + "'", ele, ex);
			}
			//在解析完成alias元素之后,发送容器别名处理完成事件
			getReaderContext().fireAliasRegistered(name, alias, extractSource(ele));
		}
	}

	/**
	 * 解析Bean资源文档对象的普通元素
	 */
	protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		//BeanDefinitionHolder是对BeanDefinition的封装,即Bean定义的封装类
		//对文档对象中bean元素的解析由BeanDefinitionParserDelegate实现
		if (bdHolder != null) {
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// Register the final decorated instance.
				//向Spring IOC容器注册解析得到的Bean定义,这是Bean定义向IOC容器注册的入口
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			} catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			// Send registration event.
			//在完成向Spring IOC容器注册解析得到的Bean定义之后,发送注册事件
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}
7>、在上一步的processBeanDefinition()方法中调用BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()) 向Spring IOC容器注册解析得到的Bean,这是Bean定义向IOC容器注册的入口
	public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		// Register bean definition under primary name.
		//获取解析的BeanDefinition的名称
		String beanName = definitionHolder.getBeanName();
		//向Spring IOC容器注册BeanDefinition
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// Register aliases for bean name, if any.
		// 如果解析的BeanDefinition有别名,向Spring IOC容器注册别名
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String alias : aliases) {
				registry.registerAlias(beanName, alias);
			}
		}
	}
8>、调到DefaultListableBeanFactory.java的registerBeanDefinition()方法把解析出来的BeanDefinition 注册到本类的成员变量beanDefinitionMap中。
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {

		Assert.hasText(beanName, "Bean name must not be empty");
		Assert.notNull(beanDefinition, "BeanDefinition must not be null");

		if (beanDefinition instanceof AbstractBeanDefinition) {
			try {
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
			}
		}

		BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
		if (existingDefinition != null) {
			if (!isAllowBeanDefinitionOverriding()) {
				throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
			}
			else if (existingDefinition.getRole() < beanDefinition.getRole()) {
				// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
				if (logger.isInfoEnabled()) {
					logger.info("Overriding user-defined bean definition for bean '" + beanName +
							"' with a framework-generated bean definition: replacing [" +
							existingDefinition + "] with [" + beanDefinition + "]");
				}
			}
			else if (!beanDefinition.equals(existingDefinition)) {
				if (logger.isDebugEnabled()) {
					logger.debug("Overriding bean definition for bean '" + beanName +
							"' with a different definition: replacing [" + existingDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			else {
				if (logger.isTraceEnabled()) {
					logger.trace("Overriding bean definition for bean '" + beanName +
							"' with an equivalent definition: replacing [" + existingDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}
		else {
			if (hasBeanCreationStarted()) {
				// Cannot modify startup-time collection elements anymore (for stable iteration)
				synchronized (this.beanDefinitionMap) {
					this.beanDefinitionMap.put(beanName, beanDefinition);
					List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
					updatedDefinitions.addAll(this.beanDefinitionNames);
					updatedDefinitions.add(beanName);
					this.beanDefinitionNames = updatedDefinitions;
					removeManualSingletonName(beanName);
				}
			}
			else {
				// Still in startup registration phase
				this.beanDefinitionMap.put(beanName, beanDefinition);
				this.beanDefinitionNames.add(beanName);
				removeManualSingletonName(beanName);
			}
			this.frozenBeanDefinitionNames = null;
		}

		if (existingDefinition != null || containsSingleton(beanName)) {
			resetBeanDefinition(beanName);
		}
	}

到这里,终于把BeanDefinition 解析出来放到BeanFactory(DefaultListableBeanFactory)的map(beanDefinitionMap)容器中。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吃透Java

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值