Spring源码-IOC之ClassPathXmlApplicationContext#refresh

版本 Spring Framework 6.0.9​

1. 前言

了解过refresh大致流程后,紧接着上一篇文章,继续浅析下ClassPathXmlApplicationContext实例化过程的第三部分refresh()。

public class Main {

	public static void main(String[] ags) {
		// 创建ioc容器
		ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
	}
}

public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {

	public ClassPathXmlApplicationContext(String... configLocations) throws BeansException {
		this(configLocations, true, null);
	}

	public ClassPathXmlApplicationContext(
			String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {
		// 调用基类AbstractApplicationContext构造方法,创建资源路径解析器,默认值是ResourcePatternResolver
		super(parent);
		// 设置上下文的配置路径
		setConfigLocations(configLocations);
		if (refresh) {
			// 调用父类AbstractApplicationContext的refresh方法
			refresh();
		}
	}

    // 省略其他代码...

}

在示例中,main方法使用的ClassPathXmlApplicationContext的有参构造,refresh缺省值是true,默认调用refresh()方法。

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		// 调用refreshBeanFactory方法来刷新当前Application的BeanFactory,由子类实现,该实例包含了所有的Bean定义信息,可以用于创建和管理Bean对象
		refreshBeanFactory();
		// 返回刷新后的BeanFactory实例,由子类实现,该实例可以用于后续的Bean操作,如获取Bean,注册Bean后置处理器,初始化消息源等
		return getBeanFactory();
	}
	
	protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;
	
	@Override
	public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
	// 省略其他代码...
}

父类AbstractApplicationContext对refresh方法做了基本实现,也会调用子类重写的方法来完成整个刷新功能,下面主要关注refresh中obtainFreshBeanFactory阶段的模板方法,refresh的其他阶段基本是AbstractApplicationContext的代码。

在这里插入图片描述

ClassPathXmlApplicationContext是AbstractRefreshableApplicationContext的子类,obtainFreshBeanFactory阶段调用其父类AbstractRefreshableApplicationContext的refreshBeanFactory方法和getBeanFactory。

2 refreshBeanFactory

public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
	@Override
	protected final void refreshBeanFactory() throws BeansException {
		// 检查是否存在BeanFactory
		if (hasBeanFactory()) {
			// 如果存在则销毁现有的所有bean
			destroyBeans();
			// 关闭BeanFactory,移除上下文和工厂之间的关系
			closeBeanFactory();
		}
		try {
			// 为此上下文创建一个新的内部 Bean 工厂。每次 refresh() 尝试都调用。DefaultListableBeanFactory实例
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			// 设置BeanFactory的序列化ID
			beanFactory.setSerializationId(getId());
			// 对BeanFactory进行一些自定义的配置,如设置是否允许覆盖同名的Bean,是否允许循环依赖等
			customizeBeanFactory(beanFactory);
			// 加载Bean定义,这是一个模板方法,由具体的子类实现,如XmlWebApplicationContext,AnnotationConfigWebApplicationContext等,
			// 根据不同的配置方式,解析XML文件或注解类,将Bean定义封装成BeanDefinition对象,并注册到BeanFactory中
			loadBeanDefinitions(beanFactory);
			// 将新创建的BeanFactory设置为当前ApplicationContext的BeanFactory
			this.beanFactory = beanFactory;
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}
	// 省略其他代码...
}

2.1 hasBeanFactory

	protected final boolean hasBeanFactory() {
		// 判断当前上下文bean工厂是否为空
		return (this.beanFactory != null);
	}

hasBeanFactory判断当前beanFactory 属性是否为空

2.2 destroyBeans

	protected void destroyBeans() {
		getBeanFactory().destroySingletons();
	}

destroyBeans和refresh阶段发生BeansException异常调用销毁bean实例是同一个方法,具体解释看Spring源码-IOC之AbstractApplicationContext#refresh

2.3 closeBeanFactory

	@Override
	protected final void closeBeanFactory() {
		DefaultListableBeanFactory beanFactory = this.beanFactory;
		if (beanFactory != null) {
			// bean工厂的序列化id置空,同时将bean工厂serializableFactories属性移除key为上下文id的值
			beanFactory.setSerializationId(null);
			// 将上下文beanFactory属性置空
			this.beanFactory = null;
		}
	}

closeBeanFactory判断如果当前bean工厂不为空,则将其属性serializationId置空,并将上下文的beanFactory属性也置空,相当于取消bean工厂和当前上下文的关联。

2.4 createBeanFactory

	protected DefaultListableBeanFactory createBeanFactory() {
		// getInternalParentBeanFactory()
		// 如果父上下文bean工厂不为空返回该工厂,否则返回父上下文本身

		// new DefaultListableBeanFactory
		// 忽略给定的接口BeanNameAware、BeanFactoryAware、BeanClassLoaderAware
		// 为bean工厂属性instantiationStrategy赋值一个CglibSubclassingInstantiationStrategy,默认使用该对象实例化bean
		return new DefaultListableBeanFactory(getInternalParentBeanFactory());
	}

createBeanFactory实例化一个bean工厂并返回,类型为DefaultListableBeanFactory。

	@Nullable
	protected BeanFactory getInternalParentBeanFactory() {
		return (getParent() instanceof ConfigurableApplicationContext cac ?
				cac.getBeanFactory() : getParent());
	}
	
	@Override
	@Nullable
	public ApplicationContext getParent() {
		return this.parent;
	}

调用DefaultListableBeanFactory的构造方法时,还调用了getInternalParentBeanFactory方法,该方法判断当前上下文是否为ConfigurableApplicationContext的子类,如果是则返回其内部bean工厂,否则返回本身。

本案例调用ClassPathXmlApplicationContext构造方法创建ioc容器时,parent没有传值为null,所以getInternalParentBeanFactory方法返回null。

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
		implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
		
	public DefaultListableBeanFactory(@Nullable BeanFactory parentBeanFactory) {
		super(parentBeanFactory);
	}
	
	// 省略其他代码...
}

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
		implements AutowireCapableBeanFactory {
		
	private final Set<Class<?>> ignoredDependencyInterfaces = new HashSet<>();
		
	public AbstractAutowireCapableBeanFactory(@Nullable BeanFactory parentBeanFactory) {
		this();
		setParentBeanFactory(parentBeanFactory);
	}
	
	public AbstractAutowireCapableBeanFactory() {
		// 空方法
		super();
		// 忽略给定的接口BeanNameAware、BeanFactoryAware、BeanClassLoaderAware
		// 上下文以其他方式解析依赖项(接口)
		ignoreDependencyInterface(BeanNameAware.class);
		ignoreDependencyInterface(BeanFactoryAware.class);
		ignoreDependencyInterface(BeanClassLoaderAware.class);
		// 为属性instantiationStrategy赋值一个CglibSubclassingInstantiationStrategy,默认使用该对象实例化bean
		this.instantiationStrategy = new CglibSubclassingInstantiationStrategy();
	}
	
	public void ignoreDependencyInterface(Class<?> ifc) {
		this.ignoredDependencyInterfaces.add(ifc);
	}
	
	@Override
	public void setParentBeanFactory(@Nullable BeanFactory parentBeanFactory) {
		if (this.parentBeanFactory != null && this.parentBeanFactory != parentBeanFactory) {
			throw new IllegalStateException("Already associated with parent BeanFactory: " + this.parentBeanFactory);
		}
		if (this == parentBeanFactory) {
			throw new IllegalStateException("Cannot set parent bean factory to self");
		}
		this.parentBeanFactory = parentBeanFactory;
	}
	// 省略其他代码...
}

DefaultListableBeanFactory的有参构造最终是调用其父类AbstractAutowireCapableBeanFactory 的无参构造方法,该无参构造方法往ignoredDependencyInterfaces属性添加了三种类型的Aware(BeanNameAware、BeanFactoryAware、BeanClassLoaderAware),并为instantiationStrategy 属性赋予一个CglibSubclassingInstantiationStrategy对象,用于实例化bean。

setParentBeanFactory方法用来给父bean工厂属性parentBeanFactory 赋值,本案例此处入参parentBeanFactory为null。

2.5 setSerializationId

	public void setSerializationId(@Nullable String serializationId) {
		if (serializationId != null) {
			// 将当前 BeanFactory 以弱引用的方式存储到 serializableFactories 中,
			// 使用传入的 serializationId 作为键
			serializableFactories.put(serializationId, new WeakReference<>(this));
		}
		// 当前BeanFactory本身的序列化ID不为空,则移除
		else if (this.serializationId != null) {
			serializableFactories.remove(this.serializationId);
		}
		// 将传入的序列化Id赋值给当前BeanFactory序列化Id
		this.serializationId = serializationId;
	}

beanFactory.setSerializationId(getId());这段代码将入参serializationId赋值给bean工厂serializationId属性

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
		
	private String id = ObjectUtils.identityToString(this);
	
	@Override
	public String getId() {
		return this.id;
	}
	// 省略其他代码...
}

public abstract class ObjectUtils {
	public static String identityToString(@Nullable Object obj) {
		if (obj == null) {
			return EMPTY_STRING;
		}
		return obj.getClass().getName() + "@" + getIdentityHexString(obj);
	}
	// 省略其他代码...
}

getId返回当前上下文的唯一id(class对象名称+@+对象哈希码的十六进制),作为bean工厂的序列化id。

2.6 customizeBeanFactory

	protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
		if (this.allowBeanDefinitionOverriding != null) {
			beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
		}
		if (this.allowCircularReferences != null) {
			beanFactory.setAllowCircularReferences(this.allowCircularReferences);
		}
	}

customizeBeanFactory对bean工厂设置是否允许覆盖同名的Bean(allowBeanDefinitionOverriding),是否允许循环依赖(allowCircularReferences)

2.7 loadBeanDefinitions

	protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
			throws BeansException, IOException;

在这里插入图片描述
loadBeanDefinitions是一个抽象方法,由子类实现,不同类型上下文读取对应类型的资源配置,从而加载bean定义。ClassPathXmlApplicationContext是AbstractXmlApplicationContext的子类,通过读取xml的配置文件加载,即本案例的beans.xml文件。

AbstractXmlApplicationContext

public abstract class AbstractXmlApplicationContext extends AbstractRefreshableConfigApplicationContext {
	@Override
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// 为给定的 BeanFactory 创建一个新的 XmlBeanDefinitionReader,并初始化其属性
		// XmlBeanDefinitionReader.registry = 当前bean工厂DefaultListableBeanFactory
		// XmlBeanDefinitionReader.resourceLoader = 一个新的PathMatchingResourcePatternResolver
		// XmlBeanDefinitionReader.environment = 一个新的StandardEnvironment,其父类AbstractEnvironment有初始化一些东西
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

		// 这里对beanDefinitionReader的resourceLoader和environment重新赋值
		// 为bean定义加载器添加环境、资源加载器、资源实体解析器
		// XmlBeanDefinitionReader.environment = 当前上下文StandardEnvironment
		beanDefinitionReader.setEnvironment(this.getEnvironment());
		// XmlBeanDefinitionReader.resourceLoader = 当前上下文,示例是ClassPathXmlApplicationContext
		beanDefinitionReader.setResourceLoader(this);
		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

		// 初始化bean定义加载器,设置是否使用XML验证,默认值为true
		// 设置validationMode属性和namespaceAware属性
		initBeanDefinitionReader(beanDefinitionReader);
		// 加载bean定义
		loadBeanDefinitions(beanDefinitionReader);
	}
	// 省略其他代码...
}

AbstractXmlApplicationContext#loadBeanDefinitions方法中初始化了一个可解析xml的XmlBeanDefinitionReader 。再调用重载方法loadBeanDefinitions加载bean定义。

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
	public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {
		super(registry);
	}
	// 省略其他代码...
}
public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader, EnvironmentCapable {
	protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) {
		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		this.registry = registry;
		
		if (this.registry instanceof ResourceLoader _resourceLoader) {
			this.resourceLoader = _resourceLoader;
		}
		else {
			this.resourceLoader = new PathMatchingResourcePatternResolver();
		}

		if (this.registry instanceof EnvironmentCapable environmentCapable) {
			this.environment = environmentCapable.getEnvironment();
		}
		else {
			this.environment = new StandardEnvironment();
		}
	}
	// 省略其他代码...
}

XmlBeanDefinitionReader 的有参构造方法中,入参registry为bean工厂,方法体调用其父类AbstractBeanDefinitionReader 的无参构造方法,设置registry 、resourceLoader 、environment 相关属性。

案例中,org.springframework.beans.factory.support.AbstractBeanDefinitionReader#AbstractBeanDefinitionReader入参registry为新创建的DefaultListableBeanFactory,非ResourceLoader和EnvironmentCapable 的子类,所以实例化一个PathMatchingResourcePatternResolver赋值给resourceLoader ,新实例化一个StandardEnvironment赋值给environment ,对XmlBeanDefinitionReader 做了初始化。

public abstract class AbstractXmlApplicationContext extends AbstractRefreshableConfigApplicationContext {
	@Override
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// 省略其他代码...
		
		beanDefinitionReader.setEnvironment(this.getEnvironment());
		// XmlBeanDefinitionReader.resourceLoader = 当前上下文,示例是ClassPathXmlApplicationContext
		beanDefinitionReader.setResourceLoader(this);
		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

		// 省略其他代码...
	}
	// 省略其他代码...
}

调完BeanDefinitionReader构造方法,后续调用set方法对相关属性重新赋值,这里的this是当前上下文对象,从ClassPathXmlApplicationContext类继承结构上看,是实现了ResourceLoader接口。

所以当前beanDefinitionReader对象属性中,registry=DefaultListableBeanFactory对象,environment=上下文的environment,resourceLoader=上下文本身,entityResolver=新创建的ResourceEntityResolver对象。

public class ResourceEntityResolver extends DelegatingEntityResolver {

	private final ResourceLoader resourceLoader;
	
	public ResourceEntityResolver(ResourceLoader resourceLoader) {
		// 调用父类构造方法,
		// 包含一个BeansDtdResolver赋值给属性dtdResolver,从 Spring 类路径(或 JAR 文件)加载 DTD,类型都是EntityResolver
		// 包含一个PluggableSchemaResolver赋值给属性schemaResolver,使用默认映射文件模式“META-INF/spring.schemas”加载模式 URL,类型都是EntityResolver
		super(resourceLoader.getClassLoader());
		this.resourceLoader = resourceLoader;
	}
	// 省略其他代码...
}
public class DelegatingEntityResolver implements EntityResolver {
	private final EntityResolver dtdResolver;
	private final EntityResolver schemaResolver;
	
	public DelegatingEntityResolver(@Nullable ClassLoader classLoader) {
		this.dtdResolver = new BeansDtdResolver();
		this.schemaResolver = new PluggableSchemaResolver(classLoader);
	}
	// 省略其他代码...
}

ResourceEntityResolver对象包含当前上下文、BeansDtdResolver、PluggableSchemaResolver。

public abstract class AbstractXmlApplicationContext extends AbstractRefreshableConfigApplicationContext {
	private boolean validating = true;
	
	@Override
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// 省略其他代码...
		initBeanDefinitionReader(beanDefinitionReader);
		// 省略其他代码...
	}
	
	protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) {
		// 设置是否使用XML验证,validating缺省值为true
		reader.setValidating(this.validating);
	}
	// 省略其他代码...
}

initBeanDefinitionReader方法给beanDefinitionReader对象validating属性赋值,缺省值为true。子类也可重写该方法,对XmlBeanDefinitionReader 做定制配置。

public abstract class AbstractXmlApplicationContext extends AbstractRefreshableConfigApplicationContext {
	private boolean validating = true;
	
	@Override
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// 省略其他代码...
		loadBeanDefinitions(beanDefinitionReader);
		// 省略其他代码...
	}
	
	protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		// 使用包含class对象构造方法,如new ClassPathXmlApplicationContext("beans.xml", User.class),会从这里解析Resource对象
		// 返回ClassPathXmlApplicationContext.configResources属性
		Resource[] configResources = getConfigResources();
		if (configResources != null) {
			reader.loadBeanDefinitions(configResources);
		}
		// 使用不包含class对象构造方法,如new ClassPathXmlApplicationContext("beans.xml"),会从这里先解析资源路径,转成Resource对象解析
		// 返回configLocations.configResources属性
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			reader.loadBeanDefinitions(configLocations);
		}
	}
	// 省略其他代码...
}

XmlBeanDefinitionReader 对象在加载bean定义loadBeanDefinitions方法有两个,解析Resource对象获取String类型的资源路径配置,取决于创建ClassPathXmlApplicationContext时使用哪种构造方法。本案例使用不包含class对象构造方法的方法,走第二部分代码逻辑。实际上第二部分会将String类型的资源配置路径转换成Resource对象,再调用解析Resource的loadBeanDefinitions方法。

XmlBeanDefinitionReader

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
	// 省略其他代码...
}

public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader, EnvironmentCapable {

	@Override
	public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
		Assert.notNull(locations, "Location array must not be null");
		int count = 0;
		for (String location : locations) {
			count += loadBeanDefinitions(location);
		}
		return count;
	}
	
	@Override
	public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
		return loadBeanDefinitions(location, null);
	}
	// 省略其他代码...
}

loadBeanDefinitions调用XmlBeanDefinitionReader 的父类AbstractBeanDefinitionReader方法,抽象类AbstractBeanDefinitionReader 有很多loadBeanDefinitions的重载方法,从源码上看,循环解析资源配置路径。

public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader, EnvironmentCapable {

	public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
		ResourceLoader resourceLoader = getResourceLoader();
		if (resourceLoader == null) {
			throw new BeanDefinitionStoreException(
					"Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
		}

		// resourceLoader是当前上下文,实现了ResourcePatternResolver即可解析资源路径
		if (resourceLoader instanceof ResourcePatternResolver resourcePatternResolver) {
			// Resource pattern matching available.
			try {
				// 将配置路径转换成Resource,调用ClassPathXmlApplicationContext实例化过程中super(parent)中新建的PathMatchingResourcePatternResolver
				Resource[] resources = resourcePatternResolver.getResources(location);
				// 加载bean定义
				int count = loadBeanDefinitions(resources);
				if (actualResources != null) {
					Collections.addAll(actualResources, resources);
				}
				if (logger.isTraceEnabled()) {
					logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
				}
				return count;
			}
			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 count = loadBeanDefinitions(resource);
			if (actualResources != null) {
				actualResources.add(resource);
			}
			if (logger.isTraceEnabled()) {
				logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");
			}
			return count;
		}
	}
	// 省略其他代码...
}

将String解析成Resource对象逻辑在public int loadBeanDefinitions(String location, @Nullable Set actualResources)。从初始化XmlBeanDefinitionReader对象的部分,可以知道getResourceLoader方法获取resourceLoader是上下文本身,而当前上下文ClassPathXmlApplicationContext对象是ResourcePatternResolver的子类,if条件通过。
在这里插入图片描述

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
		
	private final ResourcePatternResolver resourcePatternResolver;
	
	@Override
	public Resource[] getResources(String locationPattern) throws IOException {
		return this.resourcePatternResolver.getResources(locationPattern);
	}
	// 省略其他代码...
}

resourcePatternResolver.getResources(location);是当前上下文调用其内部ResourcePatternResolver 对象getResources方法。而ResourcePatternResolver对象则是在ClassPathXmlApplicationContext构造方法中创建的PathMatchingResourcePatternResolver对象。怎么解析的细节就不展开了。本案例中返回的是ClassPathContextResource对象。

所以上下文调用getResources方法,实际上是使用PathMatchingResourcePatternResolver对象的getResources方法。上下文拓展了很多能力,但一般由上下文所持有的的其他实例对象完成。

public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader, EnvironmentCapable {
	@Override
	public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
		Assert.notNull(resources, "Resource array must not be null");
		int count = 0;
		for (Resource resource : resources) {
			count += loadBeanDefinitions(resource);
		}
		return count;
	}
	// 省略其他代码...
}

下一步解析路径配置转换后的Resource对象。

在这里插入图片描述

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
	@Override
	public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
		// 为给定的资源创建一个新的EncodedResource,不指定显式编码或字符集。
		return loadBeanDefinitions(new EncodedResource(resource));
	}
}
public class EncodedResource implements InputStreamSource {
	public EncodedResource(Resource resource) {
		this(resource, null, null);
	}
	private EncodedResource(Resource resource, @Nullable String encoding, @Nullable Charset charset) {
		super();
		Assert.notNull(resource, "Resource must not be null");
		this.resource = resource;
		this.encoding = encoding;
		this.charset = charset;
	}
	// 省略其他代码...
}

解析Resource对象方法有三个实现类,案例中创建的是XmlBeanDefinitionReader对象,调用XmlBeanDefinitionReader#loadBeanDefinitions的时候,实例化了一个EncodedResource对象,持有ClassPathContextResource对象,并未指定encoding 和charset。

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
	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);
		}

		// resourcesCurrentlyBeingLoaded是ThreadLocal,返回一个线程隔离的HashSet
		Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();

		if (!currentResources.add(encodedResource)) {
			throw new BeanDefinitionStoreException(
					"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
		}

		// 将资源对象转换成inputStream流
		try (InputStream inputStream = encodedResource.getResource().getInputStream()) {
			InputSource inputSource = new InputSource(inputStream);
			// 转码不为空设置转码
			if (encodedResource.getEncoding() != null) {
				inputSource.setEncoding(encodedResource.getEncoding());
			}
			return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException(
					"IOException parsing XML document from " + encodedResource.getResource(), ex);
		}
		finally {
			currentResources.remove(encodedResource);
			if (currentResources.isEmpty()) {
				this.resourcesCurrentlyBeingLoaded.remove();
			}
		}
	}
	// 省略其他代码...
}

encodedResource.getResource().getInputStream()中,其Resource对象是ClassPathContextResource,调用其对应的方法将Resource对象转换成InputStream,继续调用doLoadBeanDefinitions方法。

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
	protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {

		try {
			// 将流转换成Document对象,com.sun.org.apache.xerces.internal.dom.DeferredDocumentImpl
			Document doc = doLoadDocument(inputSource, resource);
			// 注册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);
		}
	}
	// 省略其他代码...
}

当前doLoadBeanDefinitions方法进一步将inputSource转换成Document对象后,继续调用registerBeanDefinitions方法。

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {

	private Class<? extends BeanDefinitionDocumentReader> documentReaderClass =
			DefaultBeanDefinitionDocumentReader.class;

	public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		// 通过反射实例化一个org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader对象
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		// getRegistry() 返回 当前上下文的bean工厂DefaultListableBeanFactory
		// getBeanDefinitionCount()返回加载bean定义之间bean定义数目,这里为0,如果通过其他方式先加载了bean定义则不为0
		int countBefore = getRegistry().getBeanDefinitionCount();
		// createReaderContext(resource) 创建一个包含使用默认映射路径(META-INF/spring.handlers)的DefaultNamespaceHandlerResolver的XmlReaderContext
		// 调用org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#registerBeanDefinitions
 		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}
	
	protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
		// 属性documentReaderClass=DefaultBeanDefinitionDocumentReader
		// 通过反射实例化DefaultBeanDefinitionDocumentReader对象
		return BeanUtils.instantiateClass(this.documentReaderClass);
	}
	// 省略其他代码...
}

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
		implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {

	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

	@Override
	public int getBeanDefinitionCount() {
		return this.beanDefinitionMap.size();
	}
	// 省略其他代码...
}

通过反射创建一个DefaultBeanDefinitionDocumentReader对象,用于解析包含bean定义的Document对象。从上文我们可知XmlBeanDefinitionReader.registry是DefaultListableBeanFactory对象,则getBeanDefinitionCount返回的是bean工厂中bean定义总数,即beanDefinitionMap属性的大小。

案例中bean工厂之前未加载过bean定义,所以beanDefinitionMap大小为0,当前XmlBeanDefinitionReader #registerBeanDefinitions放大的回参int是从Document对象加载bean定义数量。

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
	@Nullable
	private NamespaceHandlerResolver namespaceHandlerResolver;
	private ProblemReporter problemReporter = new FailFastProblemReporter();
	private ReaderEventListener eventListener = new EmptyReaderEventListener();
	private SourceExtractor sourceExtractor = new NullSourceExtractor();
	
	public XmlReaderContext createReaderContext(Resource resource) {
		// 属性problemReporter=FailFastProblemReporter实例
		// 属性eventListener=EmptyReaderEventListener实例
		// 属性sourceExtractor=NullSourceExtractor实例
		// getNamespaceHandlerResolver()放回的 缺省值是一个使用默认映射路径(META-INF/spring.handlers)的DefaultNamespaceHandlerResolver,加载NamespaceHandler实现类
		return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
				this.sourceExtractor, this, getNamespaceHandlerResolver());
	}
	public NamespaceHandlerResolver getNamespaceHandlerResolver() {
		if (this.namespaceHandlerResolver == null) {
			this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver();
		}
		return this.namespaceHandlerResolver;
	}
	// 省略其他代码...
}

在DefaultBeanDefinitionDocumentReader#registerBeanDefinitions解析之前,入参中调用createReaderContext方法实例化了XmlReaderContext对象,提供对XmlBeanDefinitionReader中配置的NamespaceHandlerResolver的访问。

其中getNamespaceHandlerResolver() 提供处理其它命名空间处理器解析器路径。自动扫描和自动装配的功能也是由这一部分解析出一个NamespaceHandler组件提供。

DefaultBeanDefinitionDocumentReader

public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {

	@Override
	public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		this.readerContext = readerContext;
		// doc.getDocumentElement() 这里返回xml的是根节点,用于判断xml是否是spring默认的命名空间,调用不同的节点解析方法
		// doc类型是com.sun.org.apache.xerces.internal.dom.DeferredDocumentImpl
		doRegisterBeanDefinitions(doc.getDocumentElement());
	}

	protected void doRegisterBeanDefinitions(Element root) {
		BeanDefinitionParserDelegate parent = this.delegate;
		// 实例化BeanDefinitionParserDelegate,为BeanDefinitionParserDelegate.defaults进行初始化
		this.delegate = createDelegate(getReaderContext(), root, parent);

		// getNamespaceURI(node) 获取所提供节点的命名空间 URI。
		// URI为空或者等于http://www.springframework.org/schema/beans,则为默认命名空间
		if (this.delegate.isDefaultNamespace(root)) {
			// 判断root的属性值是否有包含profile
			String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
			if (StringUtils.hasText(profileSpec)) {
				String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
						profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
				// 为环境属性activeProfiles设置spring.profiles.active的关联值,如果为空则为default
				// 判断是否包含xml的profile属性值,打印日志
				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;
				}
			}
		}

		// 空方法 预处理xml
		preProcessXml(root);
		// 读取bean定义,解析方法
		// 分析spring定义的元素调用org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseDefaultElement
		// 分析自定义元素调用org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(org.w3c.dom.Element)
		parseBeanDefinitions(root, this.delegate);
		// 空方法 后处理xml
		postProcessXml(root);

		this.delegate = parent;
	}
	// 省略其他代码...
}

registerBeanDefinitions方法继续调用doRegisterBeanDefinitions方法。

在doRegisterBeanDefinitions方法中,调用createDelegate方法创建了一个BeanDefinitionParserDelegate 对象,并通过该对象判断xml文件中节点是否为"http://www.springframework.org/schema/beans",如果是则判断是否包含profile属性,有profile属性但环境中不存在则直接返回。本案例中没有指定。下一步继续调用preProcessXml、parseBeanDefinitions、postProcessXml。

public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {

	protected BeanDefinitionParserDelegate createDelegate(
			XmlReaderContext readerContext, Element root, @Nullable BeanDefinitionParserDelegate parentDelegate) {

		// 实例化一个BeanDefinitionParserDelegate,给其readerContext属性赋值XmlReaderContext
		BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
		// 这里初始化delegate的defaults属性,为加载bean定义使用
		// 默认lazyInit为空false
		// 默认merge为false
		// 默认autowire为no
		// autowireCandidates默认为null
		// 默认default-init-method默认为null
		// 默认default-destroy-method默认为null
		// 设置source为null
		delegate.initDefaults(root, parentDelegate);
		return delegate;
	}
	// 省略其他代码...
}

public class BeanDefinitionParserDelegate {
	public static final String BEANS_NAMESPACE_URI = "http://www.springframework.org/schema/beans";
	public static final String MULTI_VALUE_ATTRIBUTE_DELIMITERS = ",; ";
	public static final String PROFILE_ATTRIBUTE = "profile";
	private final ReaderEventListener eventListener;
	private final DocumentDefaultsDefinition defaults = new DocumentDefaultsDefinition();
	
	public void initDefaults(Element root, @Nullable BeanDefinitionParserDelegate parent) {
		// 为defaults设置默认值
		populateDefaults(this.defaults, (parent != null ? parent.defaults : null), root);
		// 发布默认注册事件
		// 调用的XmlReaderContext.eventListener(EmptyReaderEventListener)这里是一个空方法
		this.readerContext.fireDefaultsRegistered(this.defaults);
	}
	
	protected void populateDefaults(DocumentDefaultsDefinition defaults, @Nullable DocumentDefaultsDefinition parentDefaults, Element root) {
		// 默认lazyInit为空false
		String lazyInit = root.getAttribute(DEFAULT_LAZY_INIT_ATTRIBUTE);
		if (isDefaultValue(lazyInit)) {
			// Potentially inherited from outer <beans> sections, otherwise falling back to false.
			lazyInit = (parentDefaults != null ? parentDefaults.getLazyInit() : FALSE_VALUE);
		}
		defaults.setLazyInit(lazyInit);

		// 默认merge为false
		String merge = root.getAttribute(DEFAULT_MERGE_ATTRIBUTE);
		if (isDefaultValue(merge)) {
			// Potentially inherited from outer <beans> sections, otherwise falling back to false.
			merge = (parentDefaults != null ? parentDefaults.getMerge() : FALSE_VALUE);
		}
		defaults.setMerge(merge);

		// 默认autowire为no
		String autowire = root.getAttribute(DEFAULT_AUTOWIRE_ATTRIBUTE);
		if (isDefaultValue(autowire)) {
			// Potentially inherited from outer <beans> sections, otherwise falling back to 'no'.
			autowire = (parentDefaults != null ? parentDefaults.getAutowire() : AUTOWIRE_NO_VALUE);
		}
		defaults.setAutowire(autowire);

		// autowireCandidates默认为null,如果default-autowire-candidates和父default-autowire-candidates为空
		if (root.hasAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE)) {
			defaults.setAutowireCandidates(root.getAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE));
		}
		else if (parentDefaults != null) {
			defaults.setAutowireCandidates(parentDefaults.getAutowireCandidates());
		}

		// 默认default-init-method默认为null,如果default-init-method和父default-init-method为空
		if (root.hasAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE)) {
			defaults.setInitMethod(root.getAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE));
		}
		else if (parentDefaults != null) {
			defaults.setInitMethod(parentDefaults.getInitMethod());
		}

		// 默认default-destroy-method默认为null,如果default-destroy-method和父default-destroy-method为空
		if (root.hasAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE)) {
			defaults.setDestroyMethod(root.getAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE));
		}
		else if (parentDefaults != null) {
			defaults.setDestroyMethod(parentDefaults.getDestroyMethod());
		}

		// 设置source为null
		// 最终调用的XmlBeanDefinitionReader.sourceExtractor#extractSource,sourceExtractor对象是NullSourceExtractor,extractSource是一个空方法
		defaults.setSource(this.readerContext.extractSource(root));
	}
	
	public void fireDefaultsRegistered(DefaultsDefinition defaultsDefinition) {
		this.eventListener.defaultsRegistered(defaultsDefinition);
	}
	
	public boolean isDefaultNamespace(Node node) {
		// getNamespaceURI(node) 获取所提供节点的命名空间 URI。
		// URI为空或者等于http://www.springframework.org/schema/beans,则为默认命名空间
		return isDefaultNamespace(getNamespaceURI(node));
	}
	
	public boolean isDefaultNamespace(@Nullable String namespaceUri) {
		return !StringUtils.hasLength(namespaceUri) || BEANS_NAMESPACE_URI.equals(namespaceUri);
	}
	// 省略其他代码...
}

先看一下在DefaultBeanDefinitionDocumentReader#createDelegate方法中如何实例化的BeanDefinitionParserDelegate 对象。

调用BeanDefinitionParserDelegate 对象的有参构造,创建一个提供的XmlReaderContext的BeanDefinitionParserDelegate对象。
接着调用BeanDefinitionParserDelegate#initDefaults方法,对其内部对象DocumentDefaultsDefinition的属性进行初始化,如lazyInit、autowire等。最后调用XmlReaderContext的ReaderEventListener发布关于已注册给定默认值的通知。

在这里插入图片描述
从上文知道XmlReaderContext所持有的的ReaderEventListener是EmptyReaderEventListener,是个空方法。

public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {

	protected void doRegisterBeanDefinitions(Element root) {
		
		// 省略其他代码...
		preProcessXml(root);
		parseBeanDefinitions(root, this.delegate);
		postProcessXml(root);

		this.delegate = parent;
	}

	protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		// 解析 <bean> 元素
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			// 如果有适用的命名空间,则通过名称空间处理程序来修饰给定的bean定义。
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// Register the final decorated instance.
				// 注册bean定义
				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));
		}
	}
	
	protected void preProcessXml(Element root) {
	}
	
	protected void postProcessXml(Element root) {
	}
	// 省略其他代码...
}

回到DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions方法中,preProcessXml和postProcessXml都是空方法。

parseBeanDefinitions方法判断节点是否为空或者默认命名空间,如果是则调用parseDefaultElement,否则调用BeanDefinitionParserDelegate#parseCustomElement方法。

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

parseDefaultElement分为四个部分,解析import标签、alias标签、bean标签、beans标签

import标签
	protected void importBeanDefinitionResource(Element ele) {
		// 获取resource元素
		String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
		if (!StringUtils.hasText(location)) {
			getReaderContext().error("Resource location must not be empty", ele);
			return;
		}

		// Resolve system properties: e.g. "${user.dir}"
		// 解析占位符${},获取其关联值
		location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);

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

		// Discover whether the location is an absolute or relative URI
		// 判断路径是否是相对路径或者绝对路径
		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?
		// 绝对路径
		if (absoluteLocation) {
			try {
				// 再次调用loadBeanDefinitions接口
				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.
			try {
				// 根据当前资源创建绝对路径
				int importCount;
				Resource relativeResource = getReaderContext().getResource().createRelative(location);
				// 再次调用loadBeanDefinitions接口
				if (relativeResource.exists()) {
					importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
					actualResources.add(relativeResource);
				}
				// 获取基础路径baseLocation,StringUtils.applyRelativePath(baseLocation, location)拼接完整资源路径
				else {
					String baseLocation = getReaderContext().getResource().getURL().toString();
					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]);
		getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
	}

解析resource元素中路径为绝对路径或相对路径,重新调用AbstractBeanDefinitionReader#loadBeanDefinitions相关方法解析配置路径。

alias标签
protected void processAliasRegistration(Element ele) {
		// 获取name元素
		String name = ele.getAttribute(NAME_ATTRIBUTE);
		// 获取alias元素
		String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
		boolean valid = true;
		if (!StringUtils.hasText(name)) {
			getReaderContext().error("Name must not be empty", ele);
			valid = false;
		}
		if (!StringUtils.hasText(alias)) {
			getReaderContext().error("Alias must not be empty", ele);
			valid = false;
		}
		if (valid) {
			try {
				// 将别名注册到bean工厂aliasMap中,key为别名,name为bean名称
				getReaderContext().getRegistry().registerAlias(name, alias);
			}
			catch (Exception ex) {
				getReaderContext().error("Failed to register alias '" + alias +
						"' for bean with name '" + name + "'", ele, ex);
			}
			getReaderContext().fireAliasRegistered(name, alias, extractSource(ele));
		}
	}

获取name和alias元素的值,如果都不为空,则从xmlReaderContext获取bean工厂,调用bean工厂的registerAlias方法。
在这里插入图片描述

registerAlias是bean工厂父类SimpleAliasRegistry的方法

public class SimpleAliasRegistry implements AliasRegistry {

	private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);

	@Override
	public void registerAlias(String name, String alias) {
		Assert.hasText(name, "'name' must not be empty");
		Assert.hasText(alias, "'alias' must not be empty");
		synchronized (this.aliasMap) {
			// 判断别名是否与bean名称相同
			if (alias.equals(name)) {
				this.aliasMap.remove(alias);
				if (logger.isDebugEnabled()) {
					logger.debug("Alias definition '" + alias + "' ignored since it points to same name");
				}
			}
			else {
				// 从aliasMap缓存中获取bean名称
				String registeredName = this.aliasMap.get(alias);
				if (registeredName != null) {
					if (registeredName.equals(name)) {
						// An existing alias - no need to re-register
						return;
					}
					// 判断是否允许别名重复覆盖
					if (!allowAliasOverriding()) {
						throw new IllegalStateException("Cannot define alias '" + alias + "' for name '" +
								name + "': It is already registered for name '" + registeredName + "'.");
					}
					if (logger.isDebugEnabled()) {
						logger.debug("Overriding alias '" + alias + "' definition for registered name '" +
								registeredName + "' with new target name '" + name + "'");
					}
				}
				// 检查给定的名称是否已经指向另一个方向的给定别名作为别名
				checkForAliasCircle(name, alias);
				this.aliasMap.put(alias, name);
				if (logger.isTraceEnabled()) {
					logger.trace("Alias definition '" + alias + "' registered for name '" + name + "'");
				}
			}
		}
	}
	// 省略其他代码...
}

将别名和bean名称缓存到bean工厂aliasMap中,key为别名,name为bean名称。

bean标签
	protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		// 解析 <bean> 元素
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			// 通过名称空间处理程序来修饰给定的bean定义。
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// Register the final decorated instance.
				// 注册bean定义到bean工厂
				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));
		}
	}

通过BeanDefinitionParserDelegate对象解析节点,转换成包含bean定义的对象BeanDefinitionHolder,再注册到bean工厂中。

delegate.parseBeanDefinitionElement
public class BeanDefinitionParserDelegate {
	@Nullable
	public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
		return parseBeanDefinitionElement(ele, null);
	}

	@Nullable
	public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
		// 获取id元素
		String id = ele.getAttribute(ID_ATTRIBUTE);
		// 获取name元素
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

		List<String> aliases = new ArrayList<>();
		// 如果有name元素,则按指定字符",;"分割成数组,添加到别名
		// 如字符串: "Hello, java; Hello world" 指定字符: ",;" 返回数组:[Hello, java, Hello, world]
		if (StringUtils.hasLength(nameAttr)) {
			String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
			aliases.addAll(Arrays.asList(nameArr));
		}

		// 如果没有id,并且别名不为空,则使用别名的第一个值作为bean名称
		String beanName = id;
		if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
			beanName = aliases.remove(0);
			if (logger.isTraceEnabled()) {
				logger.trace("No XML 'id' specified - using '" + beanName +
						"' as bean name and " + aliases + " as aliases");
			}
		}

		// 验证指定的bean名称和别名是否已经存在,存在则报BeanDefinitionParsingException异常
		if (containingBean == null) {
			checkNameUniqueness(beanName, aliases, ele);
		}
		// 上面的代码主要设置beanName,如果id为空并且设置了name属性,则分割后name后的第一个值作为beanName,否则id作为beanName
		// 解析 Bean 定义本身
		AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
		if (beanDefinition != null) {
			// 如果bean名称为空,为给定的bean定义生成一个bean名称
			if (!StringUtils.hasText(beanName)) {
				try {
					if (containingBean != null) {
						beanName = BeanDefinitionReaderUtils.generateBeanName(
								beanDefinition, this.readerContext.getRegistry(), true);
					}
					else {
						beanName = this.readerContext.generateBeanName(beanDefinition);
						// Register an alias for the plain bean class name, if still possible,
						// if the generator returned the class name plus a suffix.
						// This is expected for Spring 1.2/2.0 backwards compatibility.
						String beanClassName = beanDefinition.getBeanClassName();
						if (beanClassName != null &&
								beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
								!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
							aliases.add(beanClassName);
						}
					}
					if (logger.isTraceEnabled()) {
						logger.trace("Neither XML 'id' nor 'name' specified - " +
								"using generated bean name [" + beanName + "]");
					}
				}
				catch (Exception ex) {
					error(ex.getMessage(), ele);
					return null;
				}
			}
			String[] aliasesArray = StringUtils.toStringArray(aliases);
			return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
		}

		return null;
	}
	// 省略其他代码...
}

进入BeanDefinitionParserDelegate#parseBeanDefinitionElement方法,可以看出方法的上半部分主要设置beanName,如果id为空并且设置了name属性,则分割后name后的第一个值作为beanName,否则id作为beanName。

然后调用parseBeanDefinitionElement方法实例化一个AbstractBeanDefinition对象,即是bean定义,入参ele为bean元素,beanName为bean名称,containingBean为null。

最后创建一个包含bean定义,bean名称和别名数组的BeanDefinitionHolder对象。

	@Nullable
	public AbstractBeanDefinition parseBeanDefinitionElement(
			Element ele, String beanName, @Nullable BeanDefinition containingBean) {

		this.parseState.push(new BeanEntry(beanName));

		// 获取class元素
		String className = null;
		if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
			className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
		}
		// 获取parent元素
		String parent = null;
		if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
			parent = ele.getAttribute(PARENT_ATTRIBUTE);
		}

		try {
			// 实例化bean定义对象GenericBeanDefinition,设置其属性beanClass
			AbstractBeanDefinition bd = createBeanDefinition(className, parent);

			// 将给定 Bean 元素的属性应用于给定的 Bean * 定义,即解析bean元素属性
			parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
			// 设置description,用于描述bean,提高代码可读性,极少用到。
			bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

			// 解析meta,用于指定bean的元数据。元数据可以包括键值对、注释或其他自定义标记,用于描述bean的特性和行为。
			// 涉及类BeanMetadataAttribute
			parseMetaElements(ele, bd);
			// 解析lookup-method,用于在子类中重写父类的bean方法。当使用Spring的基于配置的AOP时,该标签允许子类通过返回不同的实例来重写父类的方法。
			// 涉及类LookupOverride
			parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
			// 解析replaced-method,用于在运行时替换bean中的方法。可以通过指定要替换的方法名称和相应的新实现来替换bean中的现有方法。
			// 涉及类ReplaceOverride
			parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

			// 解析constructor-arg,用于设置构造函数参数的值。当创建bean时,可以通过指定构造函数参数的值来实例化bean对象。可以使用索引或参数名称指定构造函数的参数位置,并将相应的值注入到构造函数中。
			// 涉及类ConstructorArgumentValues.ValueHolder
			parseConstructorArgElements(ele, bd);
			// 解析property,用于设置bean的属性值。它可以用于注入基本类型、引用类型或其他属性。通过指定属性名称和对应的值,可以将值注入到bean的相应属性中。
			// 涉及类PropertyValue、BeanMetadataAttribute
			parsePropertyElements(ele, bd);
			// 解析qualifier,用于标识具有相同类型的多个bean的唯一性。当存在多个同一类型的bean时,可以使用该标签为每个bean设置一个唯一的标识符,以便在注入时进行精确的匹配。
			// 涉及类AutowireCandidateQualifier、BeanMetadataAttribute
			parseQualifierElements(ele, bd);

			// 将配置资源赋值给bean定义
			bd.setResource(this.readerContext.getResource());
			// 将源赋值给bean定义,如果是ClassPathXmlApplicationContext,则返回空
			bd.setSource(extractSource(ele));

			return bd;
		}
		catch (ClassNotFoundException ex) {
			error("Bean class [" + className + "] not found", ele, ex);
		}
		catch (NoClassDefFoundError err) {
			error("Class that bean class [" + className + "] depends on not found", ele, err);
		}
		catch (Throwable ex) {
			error("Unexpected failure during bean definition parsing", ele, ex);
		}
		finally {
			this.parseState.pop();
		}

		return null;
	}

进入解析bean元素的parseBeanDefinitionElement方法,方法中创建AbstractBeanDefinition对象,并一步步解析bean元素中的标签,赋值给AbstractBeanDefinition对象。这里会用到之前初始化的DocumentDefaultsDefinition对象。

delegate.decorateBeanDefinitionIfRequired 其它命名空间
public class BeanDefinitionParserDelegate {

	public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder originalDef) {
		return decorateBeanDefinitionIfRequired(ele, originalDef, null);
	}
	
	public BeanDefinitionHolder decorateBeanDefinitionIfRequired(
			Element ele, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) {

		BeanDefinitionHolder finalDefinition = originalDef;

		// Decorate based on custom attributes first.
		NamedNodeMap attributes = ele.getAttributes();
		for (int i = 0; i < attributes.getLength(); i++) {
			Node node = attributes.item(i);
			finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
		}

		// Decorate based on custom nested elements.
		NodeList children = ele.getChildNodes();
		for (int i = 0; i < children.getLength(); i++) {
			Node node = children.item(i);
			if (node.getNodeType() == Node.ELEMENT_NODE) {
				finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
			}
		}
		return finalDefinition;
	}
	
	public BeanDefinitionHolder decorateIfRequired(
			Node node, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) {

		// 获取命名空间uri
		String namespaceUri = getNamespaceURI(node);
		if (namespaceUri != null && !isDefaultNamespace(namespaceUri)) {
			// 获取namespaceUri匹配的命名空间解析器
			// getNamespaceHandlerResolver返回DefaultNamespaceHandlerResolver,resolve获取对应解析器
			NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
			if (handler != null) {
				BeanDefinitionHolder decorated =
						handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd));
				if (decorated != null) {
					return decorated;
				}
			}
			else if (namespaceUri.startsWith("http://www.springframework.org/schema/")) {
				error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", node);
			}
			else {
				// A custom namespace, not to be handled by Spring - maybe "xml:...".
				if (logger.isDebugEnabled()) {
					logger.debug("No Spring NamespaceHandler found for XML schema namespace [" + namespaceUri + "]");
				}
			}
		}
		return originalDef;
	}

decorateBeanDefinitionIfRequired方法用来解析bean中的其他命名空间的标签。

public class XmlReaderContext extends ReaderContext {
	private final NamespaceHandlerResolver namespaceHandlerResolver;
	
	public XmlReaderContext(
			Resource resource, ProblemReporter problemReporter,
			ReaderEventListener eventListener, SourceExtractor sourceExtractor,
			XmlBeanDefinitionReader reader, NamespaceHandlerResolver namespaceHandlerResolver) {
		super(resource, problemReporter, eventListener, sourceExtractor);
		this.reader = reader;
		this.namespaceHandlerResolver = namespaceHandlerResolver;
	}
	
	public final NamespaceHandlerResolver getNamespaceHandlerResolver() {
		return this.namespaceHandlerResolver;
	}
}

readerContext.getNamespaceHandlerResolver()返回本身的namespaceHandlerResolver,而namespaceHandlerResolver是在实例化XmlReaderContext 的时候赋值。
在这里插入图片描述
在这里插入图片描述
上面也有提到,具体位置在org.springframework.beans.factory.xml.XmlBeanDefinitionReader#registerBeanDefinitions,namespaceHandlerResolver是一个DefaultNamespaceHandlerResolver对象,

this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);调用的是DefaultNamespaceHandlerResolver#resolve方法。

public class DefaultNamespaceHandlerResolver implements NamespaceHandlerResolver {
	public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers";
	public DefaultNamespaceHandlerResolver(@Nullable ClassLoader classLoader, String handlerMappingsLocation) {
		Assert.notNull(handlerMappingsLocation, "Handler mappings location must not be null");
		this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());
		this.handlerMappingsLocation = handlerMappingsLocation;
	}
	public DefaultNamespaceHandlerResolver(@Nullable ClassLoader classLoader) {
		this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION);
	}
}	

在这里插入图片描述
实例化DefaultNamespaceHandlerResolver 的时候,加载"META-INF/spring.handlers"路径下的命名空间解析器字典值。

	@Override
	@Nullable
	public NamespaceHandler resolve(String namespaceUri) {
		Map<String, Object> handlerMappings = getHandlerMappings();
		Object handlerOrClassName = handlerMappings.get(namespaceUri);
		if (handlerOrClassName == null) {
			return null;
		}
		else if (handlerOrClassName instanceof NamespaceHandler namespaceHandler) {
			return namespaceHandler;
		}
		else {
			String className = (String) handlerOrClassName;
			try {
				Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
				if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
					throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
							"] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
				}
				NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
				namespaceHandler.init();
				handlerMappings.put(namespaceUri, namespaceHandler);
				return namespaceHandler;
			}
			catch (ClassNotFoundException ex) {
				throw new FatalBeanException("Could not find NamespaceHandler class [" + className +
						"] for namespace [" + namespaceUri + "]", ex);
			}
			catch (LinkageError err) {
				throw new FatalBeanException("Unresolvable class definition for NamespaceHandler class [" +
						className + "] for namespace [" + namespaceUri + "]", err);
			}
		}
	}

DefaultNamespaceHandlerResolver#resolve方法中,通过getHandlerMappings获取所有handlerMappings路径,筛选出符合的命名空间Handler后,使用反射实例化Handler并返回解析对应的标签。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
比如在xml文件中使用p命名空间,可以获取对应的handler(SimplePropertyNamespaceHandler)解析p标签。

beans标签

递归调用DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions方法。

3. 总结

  • ClassPathXmlApplicationContext在refresh的obtainFreshBeanFactory阶段有完整的实例化bean工厂过程,包含加载bean定义。
  • 在加载bean定义的时候,有几个关键类
    • XmlBeanDefinitionReader用于读取配置路径,转换成Document对象
    • BeanDefinitionDocumentReader用于承载Document对象、XmlReaderContext对象和BeanDefinitionParserDelegate对象,也提供一定的解析xml标签能力。
    • BeanDefinitionParserDelegate是用于解析bean标签的类
    • XmlReaderContext包含bean工厂和一些实例对象,同时提供其他命名空间解析器。

4. 参考

  • 17
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值