解析spring源码,IOC加载bean资源配置文件

本文深入解析Spring框架中IOC容器加载和解析bean配置文件的过程,从ClassPathXmlApplicationContext构造方法开始,详细介绍了bean定义的加载、解析和注册机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文主要内容及做什么

主要针对spring中的ioc,采用debug方式讲解spring如何加载bean配置文件,目的是对加载过程有个大概了解,spring源码优雅且复杂。

 项目环境

spring版本号为4.0.2,jdk1.8。

spring配置文件代码:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:util="http://www.springframework.org/schema/util"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
	
	<bean id="person" class="com.test.service.PersonServiceImpl">
		<property name="name" value="hello spring"></property>
	</bean>
	
</beans>

test代码为:

public class test {
	public static void main(String[] args) {
		ApplicationContext cx = new ClassPathXmlApplicationContext("applicationContext.xml");
		PersonServiceImpl obj = cx.getBean(PersonServiceImpl.class);
		System.out.println(obj.toString());
	}
}

从上面可以看出,spring从拿到资源文件到创建并获取bean,从开发角度只需要两行代码可实现,但了解其内部原理也很重要,下面开始调试,断点进入 ApplicationContext cx = new ClassPathXmlApplicationContext("applicationContext.xml");  这一行代码。

 

1、按F5进入,进入到 ClassPathXmlApplicationContext 类的构造方法,方法第一行 super(parent); 调用了父类的构造方法,父类为AbstractXmlApplicationContext,父类构造方法中同样super(parent)继续调用其父类,同样的方式分别调用了AbstractRefreshableConfigApplicationContext,AbstractApplicationContext,DefaultResourceLoader;一直调用父类构造方法,初始化了一个空的ApplicationContext对象。

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
			throws BeansException {

		super(parent);
		setConfigLocations(configLocations);
		if (refresh) {
			refresh();
		}
	}

2、setConfigLocations(configLocations) 方法主要是解析spring的配置文件地址,并赋值到成员变量 private String[] configLocations 中,可以看到为数组类型,可配置多个。

 

3、进入 ClassPathXmlApplicationContext 类的 refresh() 方法,ClassPathXmlApplicationContext 类本身没实现refresh() 方法,而是继承了其父类 AbstractApplicationContext 中的refresh() 方法,AbstractApplicationContext 是一个抽象类,refresh()是ApplicationContext初始化的核心,包含了初始化BeanFactory,解析XML加载BeanDefinition,注册bean处理器,注册事件添加监听等,以下为其refresh()代码:

@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.
			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);
				// Invoke factory processors registered as beans in the context.
				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.
				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;
			}
		}
	}

 

4、进入refresh()方法中的prepareRefresh()方法,主要是做些准备工作,记录开始时间,环境准备等。

/**
	 * Prepare this context for refreshing, setting its startup date and
	 * active flag as well as performing any initialization of property sources.
	 */
	protected void prepareRefresh() {
		this.startupDate = System.currentTimeMillis();
		synchronized (this.activeMonitor) {
			this.active = true;
		}
		if (logger.isInfoEnabled()) {
			logger.info("Refreshing " + this);
		}
		// Initialize any placeholder property sources in the context environment
		initPropertySources();
		// Validate that all properties marked as required are resolvable
		// see ConfigurablePropertyResolver#setRequiredProperties
		getEnvironment().validateRequiredProperties();
	}

 

5、进入 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory() ,创建一个beanFactory,并且解析xml中的bean定义,放置在bean工厂当中,obtainFreshBeanFactory()方法代码:

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
	refreshBeanFactory();
	ConfigurableListableBeanFactory beanFactory = getBeanFactory();
	if (logger.isDebugEnabled()) {
		logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
	}
	return beanFactory;
}

 

6、进入refreshBeanFactory()方法,是在 AbstractRefreshableApplicationContext 抽象类中,代码:

protected final void refreshBeanFactory() throws BeansException {
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
			customizeBeanFactory(beanFactory);
			loadBeanDefinitions(beanFactory);
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}

它主要完成如下:

1)hasBeanFactory()判断当前context是否持有beanFactory,如果已经存在则销毁所有单例Bean的实例,再把当前beanFactory设置为null;

2)createBeanFactory()初始化新的beanFactory,类型为DefaultListableBeanFactory;

3)customizeBeanFactory(beanFactory)设定beanFactory的一些属性;

4)loadBeanDefinitions(beanFactory)加载BeanDefinitions,这是最为核心的一步

 

7、进入 DefaultListableBeanFactory beanFactory = createBeanFactory() 方法,直接新创建了一个 DefaultListableBeanFactory类型的beanFactory并且返回,在创建的同时初始化存放bean相关属性的缓存,一般都是使用Hahsmap或者ConcurrentHashMap;

protected DefaultListableBeanFactory createBeanFactory() {
		return new DefaultListableBeanFactory(getInternalParentBeanFactory());
	}

 

8、返回来进入 refreshBeanFactory() 方法中关键的方法 loadBeanDefinitions(beanFactory),在抽象类 AbstractXmlApplicationContext 中,传入了创建好的beanFactory,代码:

/**
	 * Loads the bean definitions via an XmlBeanDefinitionReader.
	 * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
	 * @see #initBeanDefinitionReader
	 * @see #loadBeanDefinitions
	 */
	@Override
	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);
	}

 

9、来看 XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory) 这行代码,新建读取器 XmlBeanDefinitionReader,Reader是用来读取并解析xml文件,XmlBeanDefinitionReader 为抽象类,XmlBeanDefinitionReader 实现了 BeanDefinitionReader 接口,覆写了loadBeanDefinitions方法。

 

10、进入关键方法 loadBeanDefinitions(beanDefinitionReader):

/**
	 * Load the bean definitions with the given XmlBeanDefinitionReader.
	 * <p>The lifecycle of the bean factory is handled by the {@link #refreshBeanFactory}
	 * method; hence this method is just supposed to load and/or register bean definitions.
	 * @param reader the XmlBeanDefinitionReader to use
	 * @throws BeansException in case of bean registration errors
	 * @throws IOException if the required XML document isn't found
	 * @see #refreshBeanFactory
	 * @see #getConfigLocations
	 * @see #getResources
	 * @see #getResourcePatternResolver
	 */
	protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		Resource[] configResources = getConfigResources();
		if (configResources != null) {
			reader.loadBeanDefinitions(configResources);
		}
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			reader.loadBeanDefinitions(configLocations);
		}
	}

注解说的是用 XmlBeanDefinitionReader 读取器加载bean定义,其中出现了两重载方法loadBeanDefinitions(),来看下getConfigResources()方法是怎么定义的:

ClassPathXmlApplicationContext 类中的方法:

protected Resource[] getConfigResources() {
	return this.configResources;
}

 AbstractRefreshableConfigApplicationContext ClassPathXmlApplicationContext 父类,

AbstractRefreshableConfigApplicationContext 抽象类中的方法:

protected String[] getConfigLocations() {
		return (this.configLocations != null ? this.configLocations : getDefaultConfigLocations());
	}

可以看到是获取 ApplicationContext 子类的常量值,所以,到底是configLocations 还是configResources ,与最初实例化ClassPathXmlApplicationContext 对象选择的构造方法相关,实例化 applicationContext 对象的方式是new ClassPathXmlApplicationContext(“applicationContext.xml”),那么setConfigLocations方法就会被调用:

String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			reader.loadBeanDefinitions(configLocations);
		}

 

11、进入 reader.loadBeanDefinitions(configLocations) 方法,进入了 AbstractBeanDefinitionReader 抽象类,它为XmlBeanDefinitionReader 类的父类,

public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
		Assert.notNull(locations, "Location array must not be null");
		int counter = 0;
		for (String location : locations) {
			counter += loadBeanDefinitions(location);
		}
		return counter;
	}

这个方法返回值为所找到的bean定义的个数,但是这里可以看出,在调用它的方法内并没有接收和使用这个返回值。

在最初设定的资源路径为classpath下的applicationContext.xml,所以这个方法的参数值为[applicationContext.xml]

 

12,进入loadBeanDefinitions(location)方法:

public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
		return loadBeanDefinitions(location, null);
	}

再进去:

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;
		}
	}

首先getResourceLoader()获取初始化applicationcontext过程中设置的资源加载器,断定是否为ResourcePatternResolver类型。

进入if中的 loadBeanDefinitions(resources) 方法:

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;
	}

 

13,进入loadBeanDefinitions(),发现从AbstractBeanDefinitionReader 抽象类跳到 XmlBeanDefinitionReader 类,AbstractBeanDefinitionReader XmlBeanDefinitionReader 的父类:

public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
		return loadBeanDefinitions(new EncodedResource(resource));
	}

上述代码把Resource对象包装成EncodedResource对象,

再进到 loadBeanDefinitions() 方法中:

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
		Assert.notNull(encodedResource, "EncodedResource must not be null");
		if (logger.isInfoEnabled()) {
			logger.info("Loading XML bean definitions from " + encodedResource.getResource());
		}

		Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
		if (currentResources == null) {
			currentResources = new HashSet<EncodedResource>(4);
			this.resourcesCurrentlyBeingLoaded.set(currentResources);
		}
		if (!currentResources.add(encodedResource)) {
			throw new BeanDefinitionStoreException(
					"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
		}
		try {
			InputStream inputStream = encodedResource.getResource().getInputStream();
			try {
				InputSource inputSource = new InputSource(inputStream);
				if (encodedResource.getEncoding() != null) {
					inputSource.setEncoding(encodedResource.getEncoding());
				}
				return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
			}
			finally {
				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();
			}
		}
	}

上述方法中获取了资源的InputSource源,InputSource类为处理XML文件辅助类

 

14、进入 doLoadBeanDefinitions(inputSource, encodedResource.getResource()) 方法:

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {
		try {
			Document doc = doLoadDocument(inputSource, resource);
			return registerBeanDefinitions(doc, resource);
		}
		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);
		}
	}

doLoadDocument(inputSource, resource) 方法返回的资源的Document对象

 

15,进入 registerBeanDefinitions(doc, resource) 方法中:

/**
	 * Register the bean definitions contained in the given DOM document.
	 * Called by {@code loadBeanDefinitions}.
	 * <p>Creates a new instance of the parser class and invokes
	 * {@code registerBeanDefinitions} on it.
	 * @param doc the DOM document
	 * @param resource the resource descriptor (for context information)
	 * @return the number of bean definitions found
	 * @throws BeanDefinitionStoreException in case of parsing errors
	 * @see #loadBeanDefinitions
	 * @see #setDocumentReaderClass
	 * @see BeanDefinitionDocumentReader#registerBeanDefinitions
	 */
	public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		documentReader.setEnvironment(this.getEnvironment());
		int countBefore = getRegistry().getBeanDefinitionCount();
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

看注解,Register the bean definitions contained in the given DOM document,从给定的dom对象中注册bean定义。

首先创建了 BeanDefinitionDocumentReader 对象,BeanDefinitionDocumentReader类有两个作用,完成 BeanDefinition 的解析和注册。

int countBefore = getRegistry().getBeanDefinitionCount()获取先前存在的BeanDefinition个数,用于计算新注册的BeanDefinition个数。

进入 getBeanDefinitionCount() 方法,DefaultListableBeanFactory类中的getBeanDefinitionCount()方法:

public int getBeanDefinitionCount() {
		return this.beanDefinitionMap.size();
	}
/** Map of bean definition objects, keyed by bean name */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);

beanDefinitionMap是个ConcurrentHashMap,用于存放bean,key为String类型,value为BeanDefinition类型,BeanDefinition是一个接口,具有很多类型的实现子类,spring默认使用其子类GenericBeanDefinitionGenericBeanDefinition属性很少,大部分的继承自AbstractBeanDefinition类。至于 DefaultListableBeanFactory 类,很多人都说 DefaultListableBeanFactory 是spring ioc最为核心的类,说它是spring ioc的发动机,聚集了ioc大部分核心公共方法和受保护的方法。

由于之前没有注册过BeanDefinition,所以countBefore值为0。

 

16、进入documentReader.registerBeanDefinitions(doc, createReaderContext(resource)):

public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		this.readerContext = readerContext;
		logger.debug("Loading bean definitions");
		Element root = doc.getDocumentElement();
		doRegisterBeanDefinitions(root);
	}

获取了dom对象的root根元素。

 

17、进入 doRegisterBeanDefinitions() 方法:

/**
	 * Register each bean definition within the given root {@code <beans/>} element.
	 * @throws IllegalStateException if {@code <beans profile="..."} attribute is present
	 * and Environment property has not been set
	 * @see #setEnvironment
	 */
	protected void doRegisterBeanDefinitions(Element root) {
		String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
		if (StringUtils.hasText(profileSpec)) {
			Assert.state(this.environment != null, "Environment must be set for evaluating profiles");
			String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
					profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
			if (!this.environment.acceptsProfiles(specifiedProfiles)) {
				return;
			}
		}

		// Any nested <beans> elements will cause recursion in this method. In
		// order to propagate and preserve <beans> default-* attributes correctly,
		// keep track of the current (parent) delegate, which may be null. Create
		// the new (child) delegate with a reference to the parent for fallback purposes,
		// then ultimately reset this.delegate back to its original (parent) reference.
		// this behavior emulates a stack of delegates without actually necessitating one.
		BeanDefinitionParserDelegate parent = this.delegate;
		this.delegate = createDelegate(this.readerContext, root, parent);

		preProcessXml(root);
		parseBeanDefinitions(root, this.delegate);
		postProcessXml(root);

		this.delegate = parent;
	}

 

18、parseBeanDefinitions 方法传入了资源文件的根元素和新建的代理对象,进入 parseBeanDefinitions(root, this.delegate):

/**
	 * Parse the elements at the root level in the document:
	 * "import", "alias", "bean".
	 * @param root the DOM root element of the document
	 */
	protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		if (delegate.isDefaultNamespace(root)) {
			NodeList nl = root.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				if (node instanceof Element) {
					Element ele = (Element) node;
					if (delegate.isDefaultNamespace(ele)) {
						parseDefaultElement(ele, delegate);
					}
					else {
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			delegate.parseCustomElement(root);
		}
	}

parseDefaultElement 是对根元素一步一步解析,当解析到定义好的<bean>元素时,node即为Element,强制转换为Element,进入了元素解析 parseDefaultElement(ele, delegate) 方法。

 

19、进入parseDefaultElement(ele, delegate):

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			importBeanDefinitionResource(ele);
		}
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			processAliasRegistration(ele);
		}
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			processBeanDefinition(ele, delegate);
		}
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// recurse
			doRegisterBeanDefinitions(ele);
		}
	}

 这里判断资源文件中设置bean格式,最初是用普通bean定义的形式,BEAN_ELEMENT的值为"bean"。

 

20、进入processBeanDefinition(ele, delegate):

/**
	 * Process the given bean element, parsing the bean definition
	 * and registering it with the registry.
	 */
	protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// Register the final decorated instance.
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			// Send registration event.
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}

利用代理对象创建了一个BeanDefinition持有者,作为参数。

 

21、进入 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()):

/**
	 * Register the given bean definition with the given bean factory.
	 * @param definitionHolder the bean definition including name and aliases
	 * @param registry the bean factory to register with
	 * @throws BeanDefinitionStoreException if registration failed
	 */
	public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		// Register bean definition under primary name.
		String beanName = definitionHolder.getBeanName();
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// Register aliases for bean name, if any.
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String aliase : aliases) {
				registry.registerAlias(beanName, aliase);
			}
		}
	}

取到 definitionHolder 的beanname为资源文件bean的id值,definitionHolder.getBeanDefinition()返回对象为 BeanDefinition 类型,其封装了bean定的类的全路径和相应的属性值。

 

22、进入 registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()):

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);
		}
	}

	synchronized (this.beanDefinitionMap) {
		BeanDefinition oldBeanDefinition = this.beanDefinitionMap.get(beanName);
		if (oldBeanDefinition != null) {
			if (!this.allowBeanDefinitionOverriding) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
						"': There is already [" + oldBeanDefinition + "] bound.");
			}
			else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
				// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
				if (this.logger.isWarnEnabled()) {
					this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
							" with a framework-generated bean definition ': replacing [" +
							oldBeanDefinition + "] with [" + beanDefinition + "]");
				}
			}
			else {
				if (this.logger.isInfoEnabled()) {
					this.logger.info("Overriding bean definition for bean '" + beanName +
							"': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
				}
			}
		}
		else {
			this.beanDefinitionNames.add(beanName);
			this.frozenBeanDefinitionNames = null;
		}
		this.beanDefinitionMap.put(beanName, beanDefinition);
	}

	resetBeanDefinition(beanName);
}
/** List of bean definition names, in registration order */
	private final List<String> beanDefinitionNames = new ArrayList<String>();
/** Map of bean definition objects, keyed by bean name */
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);

beanDefinitionMap 是存放bean的Map,使用synchronized锁住避免多线程问题,再把 beanDefinitionput 进 beanDefinitionMap中存放起来,bean的id作为key值,可见,spring存放我们通常定义的bean就是使用初始容量为64的ConcurrentHashMap。

 

23、 看resetBeanDefinition:

/**
	 * Reset all bean definition caches for the given bean,
	 * including the caches of beans that are derived from it.
	 * @param beanName the name of the bean to reset
	 */
	protected void resetBeanDefinition(String beanName) {
		// Remove the merged bean definition for the given bean, if already created.
		clearMergedBeanDefinition(beanName);

		// Remove corresponding bean from singleton cache, if any. Shouldn't usually
		// be necessary, rather just meant for overriding a context's default beans
		// (e.g. the default StaticMessageSource in a StaticApplicationContext).
		destroySingleton(beanName);

		// Remove any assumptions about by-type mappings.
		clearByTypeCache();

		// Reset all bean definitions that have the given bean as parent (recursively).
		for (String bdName : this.beanDefinitionNames) {
			if (!beanName.equals(bdName)) {
				BeanDefinition bd = this.beanDefinitionMap.get(bdName);
				if (beanName.equals(bd.getParentName())) {
					resetBeanDefinition(bdName);
				}
			}
		}
	}
/**
	 * Remove the merged bean definition for the specified bean,
	 * recreating it on next access.
	 * @param beanName the bean name to clear the merged definition for
	 */
	protected void clearMergedBeanDefinition(String beanName) {
		this.mergedBeanDefinitions.remove(beanName);
	}

resetBeanDefinition 方法的参数只有一个,beanName,也就是定义bean的id值,主要是做一些缓存的清理和更新,spring缓存机制篇幅也比较多,至此,就完成了spring资源文件的加载和解析。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值