文章参考来自:https://www.cnblogs.com/ITtan… 文章代码来自 spring-boot 1.4.1 Release 版本
Spring IoC 容器对 Bean 定义资源的载入是从 refresh()函数开始的,refresh()是一个模板方法,refresh()方法的作用是:在创建 IoC 容器前,如果已经有容器存在,则需要把已有的容器销毁和关闭,以保证在 refresh 之后使用的是新建立起来的 IoC 容器。refresh 的作用类似于对 IoC 容器的重启,在新建立好的容器中对容器进行初始化,对 Bean 定义资源进行载入
public void refresh() throws BeansException, IllegalStateException {
Object var1 = this.startupShutdownMonitor;
synchronized(this.startupShutdownMonitor) {
// 调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识
this.prepareRefresh();
// 告诉子类启动 refreshBeanFactory()方法,Bean 定义资源文件的载入从
// 子类的 refreshBeanFactory()方法启动
// 这个 bean 的载入过程 包括对 xml 的解析和加载为 BeanDefinitions 都是从 this.obtainFreshBeanFactory()这里进入
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
/* 这之后的代码都是注册容器的信息源和生命周期事件 */
// 为 BeanFactory 配置容器特性,例如类加载器、事件处理器等
this.prepareBeanFactory(beanFactory);
try {
// 为容器的某些子类指定特殊的 BeanPost 事件处理器
this.postProcessBeanFactory(beanFactory);
// 调用所有注册的 BeanFactoryPostProcessor 的 Bean
this.invokeBeanFactoryPostProcessors(beanFactory);
// 为 BeanFactory 注册 BeanPost 事件处理器.
//BeanPostProcessor 是 Bean 后置处理器,用于监听容器触发的事件
this.registerBeanPostProcessors(beanFactory);
// 初始化信息源,和国际化相关.
this.initMessageSource();
// 初始化容器事件传播器.
this.initApplicationEventMulticaster();
// 调用子类的某些特殊 Bean 初始化方法
this.onRefresh();
// 为事件传播器注册事件监听器.
this.registerListeners();
// 初始化所有剩余的单态 Bean.
this.finishBeanFactoryInitialization(beanFactory);
// 初始化容器的生命周期事件处理器,并发布容器的生命周期事件
this.finishRefresh();
} catch (BeansException var9) {
if (this.logger.isWarnEnabled()) {
this.logger.warn(“Exception encountered during context initialization – cancelling refresh attempt: ” + var9);
}
// 销毁以创建的单态 Bean
this.destroyBeans();
// 取消 refresh 操作,重置容器的同步标识.
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}
}
}
AbstractRefreshableApplicationContext 类:AbstractRefreshableApplicationContext 中只定义了抽象的 loadBeanDefinitions 方法,容器真正调用的是其子类 AbstractXmlApplicationContext 对该方法的实现
protected final void refreshBeanFactory() throws BeansException {
// 如果已经创建了 BeanFactory,则销毁并关闭 BeanFactory
if (this.hasBeanFactory()) {
this.destroyBeans();
this.closeBeanFactory();
}
try {
// 创建了一个 IOC 容器
DefaultListableBeanFactory beanFactory = this.createBeanFactory();
beanFactory.setSerializationId(this.getId());
/ 对 IoC 容器进行定制化,如设置启动参数,开启注解的自动装配等
this.customizeBeanFactory(beanFactory);
// 调用载入 Bean 定义的方法,主要这里又使用了一个委派模式,在当前类中只定义了抽象的 loadBeanDefinitions 方法,具体的实现调用子类容器
this.loadBeanDefinitions(beanFactory);
Object var2 = this.beanFactoryMonitor;
synchronized(this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
} catch (IOException var5) {
throw new ApplicationContextException(“I/O error parsing bean definition source for ” + this.getDisplayName(), var5);
}
}
AbstractXmlApplicationContext 类:
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// 创建 XmlBeanDefinitionReader,即创建 Bean 读取器,并通过回调设置到容器中去,容器使用该读取器读取 Bean 定义资源
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
beanDefinitionReader.setEnvironment(this.getEnvironment());
// 为 Bean 读取器设置 Spring 资源加载器,AbstractXmlApplicationContext 的
// 祖先父类 AbstractApplicationContext 继承 DefaultResourceLoader,因此,容器本身也是一个资源加载器
beanDefinitionReader.setResourceLoader(this);
// 为 Bean 读取器设置 SAX xml 解析器
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// 当 Bean 读取器读取 Bean 定义的 Xml 资源文件时,启用 Xml 的校验机制
this.initBeanDefinitionReader(beanDefinitionReader);
//Bean 读取器真正实现加载的方法
this.loadBeanDefinitions(beanDefinitionReader);
}
protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) {
reader.setValidating(this.validating);
}
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = this.getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = this.getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
@Nullable
protected Resource[] getConfigResources() {
return null;
}
在其抽象父类 AbstractBeanDefinitionReader 中定义了载入过程
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
// 获取 resourceLoader
ResourceLoader resourceLoader = this.getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(“Cannot import bean definitions from location [” + location + “]: no ResourceLoader available”);
} else {
int loadCount;
if (!(resourceLoader instanceof ResourcePatternResolver)) {
// 将指定位置的 Bean 定义资源文件解析为 Spring IoC 容器封装的资源
// 加载多个指定位置的 Bean 定义资源文件 完成具体的资源定位的工作
Resource resource = resourceLoader.getResource(location);
// 加载资源 开始我们的第二步操作 转换为 BeanDefinition 对象
loadCount = this.loadBeanDefinitions((Resource)resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (this.logger.isDebugEnabled()) {
this.logger.debug(“Loaded ” + loadCount + ” bean definitions from location [” + location + “]”);
}
return loadCount;
} else {
try {
// 将指定位置的 Bean 定义资源文件解析为 Spring IoC 容器封装的资源
// 加载单个指定位置的 Bean 定义资源文件
Resource[] resources = ((ResourcePatternResolver)resourceLoader).getResources(location);
// 加载资源 开始我们的第二步操作 转换为 BeanDefinition 对象
loadCount = this.loadBeanDefinitions(resources);
if (actualResources != null) {
Resource[] var6 = resources;
int var7 = resources.length;
for(int var8 = 0; var8 < var7; ++var8) {
Resource resource = var6[var8];
actualResources.add(resource);
}
}
if (this.logger.isDebugEnabled()) {
this.logger.debug(“Loaded ” + loadCount + ” bean definitions from location pattern [” + location + “]”);
}
return loadCount;
} catch (IOException var10) {
throw new BeanDefinitionStoreException(“Could not resolve bean definition resource pattern [” + location + “]”, var10);
}
}
}
}
具体加载资源的方法 首先,调用资源加载器的获取资源方法 resourceLoader.getResource(location),获取到要加载的资源。其次,真正执行加载功能是其子类 XmlBeanDefinitionReader 的 loadBeanDefinitions 方法。资源定位到这里就结束 最终返回的是一个 Resource 的对象来进行 BeanDefinition 的载入。在定位完成后, 为 BeanDefinition 的载入创客 I / O 条件,但是具体的载入还没有开始载入。
public Resource getResource(String location) {
Assert.notNull(location, “Location must not be null”);
Iterator var2 = this.protocolResolvers.iterator();
Resource resource;
do {
if (!var2.hasNext()) {
// 处理 / 开头的定位
if (location.startsWith(“/”)) {
return this.getResourceByPath(location);
}
// 带有 classpath 标识的 Resource
if (location.startsWith(“classpath:”)) {
return new ClassPathResource(location.substring(“classpath:”.length()), this.getClassLoader());
}
try {
// 处理 URL 标识的 Resource 定位
URL url = new URL(location);
return (Resource)(ResourceUtils.isFileURL(url) ? new FileUrlResource(url) : new UrlResource(url));
} catch (MalformedURLException var5) {
// 如果不存 classpath、Url、/ 标志的 就教给他处理
return this.getResourceByPath(location);
}
}
ProtocolResolver protocolResolver = (ProtocolResolver)var2.next();
resource = protocolResolver.resolve(location, this);
} while(resource == null);
return resource;
}
protected Resource getResourceByPath(String path) {
if (path != null && path.startsWith(“/”)) {
path = path.substring(1);
}
// 这里使用文件系统资源对象来定义 bean 文件
return new FileSystemResource(path);
}
BeanDefinition 的载入分成两部分, 首先通过 XML 的解析器得到 document 对象,但这些 document 对象没有按照 spring 的 Bean 规则进行解析。在完成 XML 解析后,才是按照 Spring 的 Bean 规则进行解析,这个解析的过程是在 documentReader 实现。
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
// 获取 resourceLoader
ResourceLoader resourceLoader = this.getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(“Cannot import bean definitions from location [” + location + “]: no ResourceLoader available”);
} else {
int loadCount;
if (!(resourceLoader instanceof ResourcePatternResolver)) {
// 将指定位置的 Bean 定义资源文件解析为 Spring IoC 容器封装的资源
// 加载多个指定位置的 Bean 定义资源文件 完成具体的资源定位的工作
Resource resource = resourceLoader.getResource(location);
// 加载资源 开始我们的第二步操作 转换为 BeanDefinition 对象
loadCount = this.loadBeanDefinitions((Resource)resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (this.logger.isDebugEnabled()) {
this.logger.debug(“Loaded ” + loadCount + ” bean definitions from location [” + location + “]”);
}
return loadCount;
} else {
try {
// 将指定位置的 Bean 定义资源文件解析为 Spring IoC 容器封装的资源
// 加载单个指定位置的 Bean 定义资源文件
Resource[] resources = ((ResourcePatternResolver)resourceLoader).getResources(location);
// 加载资源 开始我们的第二步操作 转换为 BeanDefinition 对象
loadCount = this.loadBeanDefinitions(resources);
if (actualResources != null) {
Resource[] var6 = resources;
int var7 = resources.length;
for(int var8 = 0; var8 < var7; ++var8) {
Resource resource = var6[var8];
actualResources.add(resource);
}
}
if (this.logger.isDebugEnabled()) {
this.logger.debug(“Loaded ” + loadCount + ” bean definitions from location pattern [” + location + “]”);
}
return loadCount;
} catch (IOException var10) {
throw new BeanDefinitionStoreException(“Could not resolve bean definition resource pattern [” + location + “]”, var10);
}
}
}
}
xml 文件转换为 document 对象 再解析 BeanDefinition 这里是载入 XML 形式 Bean 定义资源文件方法
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, “EncodedResource must not be null”);
if(this.logger.isInfoEnabled()) {
this.logger.info(“Loading XML bean definitions from ” + encodedResource.getResource());
}
Set<EncodedResource> currentResources = (Set)this.resourcesCurrentlyBeingLoaded.get();
if(currentResources == null) {
currentResources = new HashSet(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if(!((Set)currentResources).add(encodedResource)) {
throw new BeanDefinitionStoreException(“Detected cyclic loading of ” + encodedResource + ” – check your import definitions!”);
} else {
int var5;
try {
// 将资源文件转为 InputStream 的 IO 流
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
// 从 InputStream 中得到 XML 的解析源
InputSource inputSource = new InputSource(inputStream);
if(encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
// 这里是具体的读取过程
var5 = this.doLoadBeanDefinitions(inputSource, encodedResource.getResource());
} finally {
//IO 流的关闭
inputStream.close();
}
} catch (IOException var15) {
throw new BeanDefinitionStoreException(“IOException parsing XML document from ” + encodedResource.getResource(), var15);
} finally {
((Set)currentResources).remove(encodedResource);
if(((Set)currentResources).isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
return var5;
}
}
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
try {
//@1 将 XML 文件转换为 DOM 对象,解析过程由 documentLoader 实现
Document doc = this.doLoadDocument(inputSource, resource);
//@2 这里是启动对 Bean 定义解析的详细过程,该解析过程会用到 Spring 的 Bean 配置规则
return this.registerBeanDefinitions(doc, resource);
} catch (BeanDefinitionStoreException var4) {
throw var4;
} catch (SAXParseException var5) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(), “Line ” + var5.getLineNumber() + ” in XML document from ” + resource + ” is invalid”, var5);
} catch (SAXException var6) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(), “XML document from ” + resource + ” is invalid”, var6);
} catch (ParserConfigurationException var7) {
throw new BeanDefinitionStoreException(resource.getDescription(), “Parser configuration exception parsing XML from ” + resource, var7);
} catch (IOException var8) {
throw new BeanDefinitionStoreException(resource.getDescription(), “IOException parsing XML document from ” + resource, var8);
} catch (Throwable var9) {
throw new BeanDefinitionStoreException(resource.getDescription(), “Unexpected exception parsing XML document from ” + resource, var9);
}
}
@1
// 使用标准的 JAXP 将载入的 Bean 定义资源转换成 document 对象
public Document loadDocument(InputSource inputSource, EntityResolver entityResolver, ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {
// 创建文件解析器工厂
DocumentBuilderFactory factory = this.createDocumentBuilderFactory(validationMode, namespaceAware);
if(logger.isDebugEnabled()) {
logger.debug(“Using JAXP provider [” + factory.getClass().getName() + “]”);
}
// 创建文档解析器
DocumentBuilder builder = this.createDocumentBuilder(factory, entityResolver, errorHandler);
// 解析 Spring 的 Bean 定义资源
return builder.parse(inputSource);
}
protected DocumentBuilderFactory createDocumentBuilderFactory(int validationMode, boolean namespaceAware) throws ParserConfigurationException {
// 创建文档解析工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(namespaceAware);
if(validationMode != 0) {
// 设置解析 XML 的校验
factory.setValidating(true);
if(validationMode == 3) {
factory.setNamespaceAware(true);
try {
factory.setAttribute(“http://java.sun.com/xml/jaxp/properties/schemaLanguage”, “http://www.w3.org/2001/XMLSchema”);
} catch (IllegalArgumentException var6) {
ParserConfigurationException pcex = new ParserConfigurationException(“Unable to validate using XSD: Your JAXP provider [” + factory + “] does not support XML Schema. Are you running on Java 1.4 with Apache Crimson? Upgrade to Apache Xerces (or Java 1.5) for full XSD support.”);
pcex.initCause(var6);
throw pcex;
}
}
}
return factory;
}
Spring IoC 容器根据定位的 Bean 定义资源文件,将其加载读入并转换成为 Document 对象过程完成。
下面是 Spring IoC 容器将载入的 Bean 定义资源文件转换为 Document 对象之后,是如何将其解析为 Spring IoC 管理的 Bean 对象并将其注册到容器中的 @2
// 按照 Spring 的 Bean 语义要求将 Bean 定义资源解析并转换为容器内部数据结构
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
/ 得到 BeanDefinitionDocumentReader 来对 xml 格式的 BeanDefinition 解析
BeanDefinitionDocumentReader documentReader = this.createBeanDefinitionDocumentReader();
// 获得容器中注册的 Bean 数量
int countBefore = this.getRegistry().getBeanDefinitionCount();
// 解析过程入口,这里使用了委派模式,BeanDefinitionDocumentReader 只是个接口
// 具体的解析实现过程有实现类 DefaultBeanDefinitionDocumentReader 完成
//@1
documentReader.registerBeanDefinitions(doc, this.createReaderContext(resource));
/ 统计解析的 Bean 数量
return this.getRegistry().getBeanDefinitionCount() – countBefore;
}
// 创建 BeanDefinitionDocumentReader 对象,解析 Document 对象
protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
return (BeanDefinitionDocumentReader)BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass));
}
DefaultBeanDefinitionDocumentReader 解析 document 对象按照 spring Bean 的定义规则转换为 BeanDefinition@1
public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
public static final String BEAN_ELEMENT = “bean”;
public static final String NESTED_BEANS_ELEMENT = “beans”;
public static final String ALIAS_ELEMENT = “alias”;
public static final String NAME_ATTRIBUTE = “name”;
public static final String ALIAS_ATTRIBUTE = “alias”;
public static final String IMPORT_ELEMENT = “import”;
public static final String RESOURCE_ATTRIBUTE = “resource”;
public static final String PROFILE_ATTRIBUTE = “profile”;
protected final Log logger = LogFactory.getLog(this.getClass());
private XmlReaderContext readerContext;
private BeanDefinitionParserDelegate delegate;
public DefaultBeanDefinitionDocumentReader() {
}
// 根据 Spring DTD 对 Bean 的定义规则解析 Bean 定义 Document 对象
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
// 获得 XML 描述符
this.readerContext = readerContext;
this.logger.debug(“Loading bean definitions”);
// 获得 Document 的根元素
Element root = doc.getDocumentElement();
this.doRegisterBeanDefinitions(root);
}
protected final XmlReaderContext getReaderContext() {
return this.readerContext;
}
protected Object extractSource(Element ele) {
return this.getReaderContext().extractSource(ele);
}
// 具体的解析过程由 BeanDefinitionParserDelegate 实现,
//BeanDefinitionParserDelegate 中定义了 Spring Bean 定义 XML 文件的各种元素
protected void doRegisterBeanDefinitions(Element root) {
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = this.createDelegate(this.getReaderContext(), root, parent);
if(this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(“profile”);
if(StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, “,; “);
if(!this.getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if(this.logger.isInfoEnabled()) {
this.logger.info(“Skipped XML bean definition file due to specified profiles [” + profileSpec + “] not matching: ” + this.getReaderContext().getResource());
}
return;
}
}
}
// 在解析 Bean 定义之前,进行自定义的解析,增强解析过程的可扩展性
this.preProcessXml(root);
// 从 Document 的根元素开始进行 Bean 定义的 Document 对象
this.parseBeanDefinitions(root, this.delegate);
// 在解析 Bean 定义之后,进行自定义的解析,增加解析过程的可扩展性
this.postProcessXml(root);
this.delegate = parent;
}
// 创建 BeanDefinitionParserDelegate,用于完成真正的解析过程
protected BeanDefinitionParserDelegate createDelegate(XmlReaderContext readerContext, Element root, BeanDefinitionParserDelegate parentDelegate) {
BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
//BeanDefinitionParserDelegate 初始化 Document 根元素
delegate.initDefaults(root, parentDelegate);
return delegate;
}
// 使用 Spring 的 Bean 规则从 Document 的根元素开始进行 Bean 定义的 Document 对象
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
//Bean 定义的 Document 对象使用了 Spring 默认的 XML 命名空间
if(delegate.isDefaultNamespace(root)) {
// 获取 Bean 定义的 Document 对象根元素的所有子节点
NodeList nl = root.getChildNodes();
for(int i = 0; i < nl.getLength(); ++i) {
Node node = nl.item(i);
// 获得 Document 节点是 XML 元素节点
if(node instanceof Element) {
Element ele = (Element)node;
//Bean 定义的 Document 的元素节点使用的是 Spring 默认的 XML 命名空间
if(delegate.isDefaultNamespace(ele)) {
// 使用 Spring 的 Bean 规则解析元素节点
this.parseDefaultElement(ele, delegate);
} else {
// 没有使用 Spring 默认的 XML 命名空间,则使用用户自定义的解 // 析规则解析元素节点
delegate.parseCustomElement(ele);
}
}
}
} else {
//Document 的根节点没有使用 Spring 默认的命名空间,则使用用户自定义的
// 解析规则解析 Document 根节点
delegate.parseCustomElement(root);
}
}
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
// 如果元素节点是 <Import> 导入元素,进行导入解析
if(delegate.nodeNameEquals(ele, “import”)) {
this.importBeanDefinitionResource(ele);
} else if(delegate.nodeNameEquals(ele, “alias”)) {
// 如果元素节点是 <Alias> 别名元素,进行别名解析
this.processAliasRegistration(ele);
} else if(delegate.nodeNameEquals(ele, “bean”)) {
// 元素节点既不是导入元素,也不是别名元素,即普通的 <Bean> 元素,
// 按照 Spring 的 Bean 规则解析元素
this.processBeanDefinition(ele, delegate);
} else if(delegate.nodeNameEquals(ele, “beans”)) {
// 如果元素节点是 <beans> 元素注册为 BeanDefintion
this.doRegisterBeanDefinitions(ele);
}
}
// 解析 <Import> 导入元素,从给定的导入路径加载 Bean 定义资源到 Spring IoC 容器中
protected void importBeanDefinitionResource(Element ele) {
/ 获取给定的导入元素的 location 属性
String location = ele.getAttribute(“resource”);
if(!StringUtils.hasText(location)) {
this.getReaderContext().error(“Resource location must not be empty”, ele);
} else {
// 获取 location 的值
location = this.getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);
Set<Resource> actualResources = new LinkedHashSet(4);
// 标识给定的导入元素的 location 是否是绝对路径
boolean absoluteLocation = false;
try {
absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
} catch (URISyntaxException var11) {
;
}
int importCount;
if(absoluteLocation) {
try {
// 使用资源读入器加载给定路径的 Bean 定义资源
importCount = this.getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
if(this.logger.isDebugEnabled()) {
this.logger.debug(“Imported ” + importCount + ” bean definitions from URL location [” + location + “]”);
}
} catch (BeanDefinitionStoreException var10) {
this.getReaderContext().error(“Failed to import bean definitions from URL location [” + location + “]”, ele, var10);
}
} else {
// 给定的导入元素的 location 是相对路径
try {
Resource relativeResource = this.getReaderContext().getResource().createRelative(location);
if(relativeResource.exists()) {
// 使用资源读入器加载 Bean 定义资源
importCount = this.getReaderContext().getReader().loadBeanDefinitions(relativeResource);
actualResources.add(relativeResource);
} else {
String baseLocation = this.getReaderContext().getResource().getURL().toString();
importCount = this.getReaderContext().getReader().loadBeanDefinitions(StringUtils.applyRelativePath(baseLocation, location), actualResources);
}
if(this.logger.isDebugEnabled()) {
this.logger.debug(“Imported ” + importCount + ” bean definitions from relative location [” + location + “]”);
}
} catch (IOException var8) {
this.getReaderContext().error(“Failed to resolve current resource location”, ele, var8);
} catch (BeanDefinitionStoreException var9) {
this.getReaderContext().error(“Failed to import bean definitions from relative location [” + location + “]”, ele, var9);
}
}
// 在解析完 <Import> 元素之后,发送容器导入其他资源处理完成事件
Resource[] actResArray = (Resource[])actualResources.toArray(new Resource[actualResources.size()]);
this.getReaderContext().fireImportProcessed(location, actResArray, this.extractSource(ele));
}
}
// 解析 <Alias> 别名元素,为 Bean 向 Spring IoC 容器注册别名
protected void processAliasRegistration(Element ele) {
// 获取 <Alias> 别名元素中 name 的属性值
String name = ele.getAttribute(“name”);
// 获取 <Alias> 别名元素中 alias 的属性值
String alias = ele.getAttribute(“alias”);
boolean valid = true;
if(!StringUtils.hasText(name)) {
this.getReaderContext().error(“Name must not be empty”, ele);
valid = false;
}
if(!StringUtils.hasText(alias)) {
this.getReaderContext().error(“Alias must not be empty”, ele);
valid = false;
}
if(valid) {
try {
// 向容器的资源读入器注册别名
this.getReaderContext().getRegistry().registerAlias(name, alias);
} catch (Exception var6) {
this.getReaderContext().error(“Failed to register alias ‘” + alias + “‘ for bean with name ‘” + name + “‘”, ele, var6);
}
// 在解析完 <Alias> 元素之后,发送容器别名处理完成事件
this.getReaderContext().fireAliasRegistered(name, alias, this.extractSource(ele));
}
}
// 解析 Bean 定义资源 Document 对象的普通元素
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// BeanDefinitionHolder 是对 BeanDefinition 的封装,即 Bean 定义的封装类
// 对 Document 对象中 <Bean> 元素的解析由 BeanDefinitionParserDelegate 实现 BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if(bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// 向 Spring IoC 容器注册解析得到的 Bean 定义,这是 Bean 定义向 IoC 容器注册的入口
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
} catch (BeanDefinitionStoreException var5) {
this.getReaderContext().error(“Failed to register bean definition with name ‘” + bdHolder.getBeanName() + “‘”, ele, var5);
}
// 在完成向 Spring IoC 容器注册解析得到的 Bean 定义之后,发送注册事件
this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
protected void preProcessXml(Element root) {
}
protected void postProcessXml(Element root) {
}
}
通过上述 Spring IoC 容器对载入的 Bean 定义 Document 解析可以看出,我们使用 Spring 时,在 Spring 配置文件中可以使用 <Import> 元素来导入 IoC 容器所需要的其他资源,Spring IoC 容器在解析时会首先将指定导入的资源加载进容器中。使用 <Ailas> 别名时,Spring IoC 容器首先将别名元素所定义的别名注册到容器中。对于既不是 <Import> 元素,又不是 <Alias> 元素的元素,即 Spring 配置文件中普通的 <Bean> 元素的解析由 BeanDefinitionParserDelegate 类的 parseBeanDefinitionElement 方法来实现。
下面是针对对 Bean 元素的解析过程
// 解析 Bean 定义资源文件中的 <Bean> 元素,这个方法中主要处理 <Bean> 元素的 id,name
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
// 获取 id 属性
String id = ele.getAttribute(“id”);
// 获取 name 属性
String nameAttr = ele.getAttribute(“name”);
List<String> aliases = new ArrayList();
// 将 Bean 元素的 name 属性全部放到 alias 属性里面
if(StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, “,; “);
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
if(!StringUtils.hasText(id) && !aliases.isEmpty()) {
beanName = (String)aliases.remove(0);
if(this.logger.isDebugEnabled()) {
this.logger.debug(“No XML ‘id’ specified – using ‘” + beanName + “‘ as bean name and ” + aliases + ” as aliases”);
}
}
if(containingBean == null) {
// 检查 bean 元素的 id 和 name 是否是唯一的
this.checkNameUniqueness(beanName, aliases, ele);
}
// 详细对 <Bean> 元素中配置的 Bean 定义进行解析的地方
AbstractBeanDefinition beanDefinition = this.parseBeanDefinitionElement(ele, beanName, containingBean);
if(beanDefinition != null) {
if(!StringUtils.hasText(beanName)) {
try {
if(containingBean != null) {
// 判断如果没有 id 和 name 属性时候是否包含子元素的 <Bean>
beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true);
} else {
// 如果 <Bean> 元素中没有配置 id、别名或者 name,且包含了子 //<Bean> 元素,为解析的 Bean 使用别名向 IoC 容器注册
beanName = this.readerContext.generateBeanName(beanDefinition);
String beanClassName = beanDefinition.getBeanClassName();
if(beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
if(this.logger.isDebugEnabled()) {
this.logger.debug(“Neither XML ‘id’ nor ‘name’ specified – using generated bean name [” + beanName + “]”);
}
} catch (Exception var9) {
this.error(var9.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
} else {
return null;
}
}
// 详细解析 bean 元素的地方
public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
String className = null;
// 是否包含 class 属性
if(ele.hasAttribute(“class”)) {
// 获取 class 属性值 不做实例化,bean 的实例化是在第一次获取 bean 的时候完成,这里只获取 class 的值
className = ele.getAttribute(“class”).trim();
}
try {
String parent = null;
// 如果 <Bean> 元素中配置了 parent 属性,则获取 parent 属性的值
if(ele.hasAttribute(“parent”)) {
parent = ele.getAttribute(“parent”);
}
// 根据 <Bean> 元素配置的 class 名称和 parent 属性值创建 BeanDefinition
// 为载入 Bean 定义信息做准备
AbstractBeanDefinition bd = this.createBeanDefinition(className, parent);
// 对当前的 <Bean> 元素中配置的一些属性进行解析和设置,如配置的单态 (singleton) 属性等
this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
// 为 <Bean> 元素解析的 Bean 设置 description 信息 bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, “description”));
// 对 <Bean> 元素的 meta(元信息)属性解析
this.parseMetaElements(ele, bd);
// 对 <Bean> 元素的 lookup-method 属性解析
this.parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
// 对 <Bean> 元素的 replaced-method 属性解析
this.parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
// 解析 <Bean> 元素的构造方法设置
this.parseConstructorArgElements(ele, bd);
// 解析 <Bean> 元素的 <property> 设置
this.parsePropertyElements(ele, bd);
// 解析 <Bean> 元素的 qualifier 属性
this.parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());
bd.setSource(this.extractSource(ele));
AbstractBeanDefinition var7 = bd;
return var7;
} catch (ClassNotFoundException var13) {
this.error(“Bean class [” + className + “] not found”, ele, var13);
} catch (NoClassDefFoundError var14) {
this.error(“Class that bean class [” + className + “] depends on not found”, ele, var14);
} catch (Throwable var15) {
this.error(“Unexpected failure during bean definition parsing”, ele, var15);
} finally {
this.parseState.pop();
}
return null;
}
通过对上述源码的分析,就会明白我们在 Spring 配置文件中 <Bean> 元素的中配置的属性就是通过该方法解析和设置到 Bean 中去的。注意:在解析 <Bean> 元素过程中没有创建和实例化 Bean 对象,只是创建了 Bean 对象的定义类 BeanDefinition,将 <Bean> 元素中的配置信息设置到 BeanDefinition 中作为记录,当依赖注入时才使用这些记录信息创建和实例化具体的 Bean 对象。上面方法中一些对一些配置如元信息(meta)、qualifier 等的解析,我们在 Spring 中配置时使用的也不多,我们在使用 Spring 的 <Bean> 元素时,配置最多的是 <property> 属性。
调用 BeanDefinitionReaderUtils 的 registerBeanDefinition 方法向 IoC 容器注册解析的 Bean
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if(bdHolder != null) {
// 通过对 document 对象的解析和封装返回一个 BeanDefinitionHolder
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// 通过这个 holder 来注册 bean 对象
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
} catch (BeanDefinitionStoreException var5) {
this.getReaderContext().error(“Failed to register bean definition with name ‘” + bdHolder.getBeanName() + “‘”, ele, var5);
}
this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
当调用 BeanDefinitionReaderUtils 向 IoC 容器注册解析的 BeanDefinition 时,真正完成注册功能的是 DefaultListableBeanFactory。
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
String[] aliases = definitionHolder.getAliases();
if(aliases != null) {
String[] var4 = aliases;
int var5 = aliases.length;
for(int var6 = 0; var6 < var5; ++var6) {
String alias = var4[var6];
registry.registerAlias(beanName, alias);
}
}
}
DefaultListableBeanFactory registerBeanDefinition 方法
// 存储注册的俄 BeanDefinition
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);
// 向 IoC 容器注册解析的 BeanDefiniton
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”);
// 校验解析的 BeanDefiniton
if(beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition)beanDefinition).validate();
} catch (BeanDefinitionValidationException var9) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, “Validation of bean definition failed”, var9);
}
}
BeanDefinition oldBeanDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
if(oldBeanDefinition != null) {
if(!this.isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, “Cannot register bean definition [” + beanDefinition + “] for bean ‘” + beanName + “‘: There is already [” + oldBeanDefinition + “] bound.”);
}
if(oldBeanDefinition.getRole() < beanDefinition.getRole()) {
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(!beanDefinition.equals(oldBeanDefinition)) {
if(this.logger.isInfoEnabled()) {
this.logger.info(“Overriding bean definition for bean ‘” + beanName + “‘ with a different definition: replacing [” + oldBeanDefinition + “] with [” + beanDefinition + “]”);
}
} else if(this.logger.isDebugEnabled()) {
this.logger.debug(“Overriding bean definition for bean ‘” + beanName + “‘ with an equivalent definition: replacing [” + oldBeanDefinition + “] with [” + beanDefinition + “]”);
}
this.beanDefinitionMap.put(beanName, beanDefinition);
} else {
if(this.hasBeanCreationStarted()) {
Map var4 = this.beanDefinitionMap;
// 注册的过程中需要线程同步,以保证数据的一致性
synchronized(this.beanDefinitionMap) {
// 把 bean 存放到 map 中
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if(this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
} else {
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if(oldBeanDefinition != null || this.containsSingleton(beanName)) {
this.resetBeanDefinition(beanName);
}
}
至此,Bean 定义资源文件中配置的 Bean 被解析过后,已经注册到 IoC 容器中,被容器管理起来,真正完成了 IoC 容器初始化所做的全部工作。现 在 IoC 容器中已经建立了整个 Bean 的配置信息,这些 BeanDefinition 信息已经可以使用,并且可以被检索,IoC 容器的作用就是对这些注册的 Bean 定义信息进行处理和维护。这些的注册的 Bean 定义信息是 IoC 容器控制反转的基础,正是有了这些注册的数据,容器才可以进行依赖注入。