解析的步骤:
1、加载web.xml、加载监听器
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
2、ContextLoaderListener
初始化initWebApplicationContext方法创建
org.springframework.web.context.support. XmlWebApplicationContext对象
3、XmlWebApplicationContext
调用loadBeanDefinitions方法,该方法主要做两件事情:初始化XmlBeanDefinitionReader、获取applicationContext.xml配置文件的路径、然后把事情交给XmlBeanDefinitionReader来处理
4、XmlBeanDefinitionReader
获取到applicationContext.xml配置文件的路径、读取配置文件的内容得到一个输入流、对输入流转码操作、然后封装成一个inputSource对象、再然后封装成一个document对象;在生成document对象的同事也生成了一个Resource对象、这两个对象分部是:document对象承载配置文件的主要内容信息、Resource承载配置文件的描述信息以及一些验证信息。
再由Resource对象创建一个XmlReaderContext。完成了以上操作XmlBeanDefinitionReader就把document对象和XmlReaderContext对象交给DefaultBeanDefinitionDocumentReader来处理
5、DefaultBeanDefinitionDocumentReader
1)、对XmlReaderContext装饰成一个BeanDefinitionParserDelegate对象;
2)、迭代document对象、把document对象拆分成Element元素逐个逐个解析;
3)、使用BeanDefinitionParserDelegate装饰对象解析Element元素或者说标签。
这里的Element元素有两种:一种是DefaultElement、另一种是CustomElement;DefaultElement包括alias、import、bean,CustomElement包括DefaultElement以外的所有元素
我们所关心的应该是第一中元素DefaultElement,看下DefaultBeanDefinitionDocumentReader解析该元素的方法:
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);
}
}
解析import标签的方法:
protected void importBeanDefinitionResource(Element ele) {
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 = SystemPropertyUtils.resolvePlaceholders(location);
Set<Resource> actualResources = new LinkedHashSet<Resource>(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 {
int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
if (logger.isDebugEnabled()) {
logger.debug("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);
if (relativeResource.exists()) {
importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
actualResources.add(relativeResource);
}
else {
String baseLocation = getReaderContext().getResource().getURL().toString();
importCount = getReaderContext().getReader().loadBeanDefinitions(
StringUtils.applyRelativePath(baseLocation, location), actualResources);
}
if (logger.isDebugEnabled()) {
logger.debug("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[actualResources.size()]);
getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
}
解析alias标签的方法:
protected void processAliasRegistration(Element ele) {
String name = ele.getAttribute(NAME_ATTRIBUTE);
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 {
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));
}
}
解析bean标签的方法:
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));
}
}
方法调用关系图:
- 大小: 195.8 KB
分享到:
相关推荐
总的来说,Spring通过源码解析XML配置文件中的默认标签,特别是`<bean>`标签,实现Bean定义的加载和注册,从而构建Bean的依赖关系图。理解这一过程对于深入掌握Spring的工作原理,优化配置,以及解决配置问题至关...
`BeanDefinitionParserDelegate`的作用是解析XML中的`<bean>`标签以及其他相关的元素,如`<import>`、`<alias>`等。在解析过程中,由于XML可以有嵌套的`<beans>`元素,`BeanDefinitionParserDelegate`使用一个parent...
- **常规标签解析**:包括`import`(导入其他配置)、`alias`(别名)、`bean`(定义Bean)等。在解析`bean`时,会创建`GenericBeanDefinition`对象,设置属性,处理元数据、lookup-method、replaced-method、构造...
3、import用于导入其他配置文件的Bean定义,这是为了加载多个配置文件,当然也可以把这些配置文件构造为一个数组(new String[] {“config1.xml”, config2.xml})传给ApplicationContext实现进行加载多个配置文件,...
rar包内含有spring2.5.6源码,解压即可使用 源代码分析,是一件既痛苦又快乐的事情,看别人写的代码是通过的,但当你能够看明白的时候,相信快乐也会随之而来,为了减少痛苦,更快的带来快乐,在这里希望通过这篇...
4. **BeanDefinition解析**:在解析过程中,会创建Bean的解析器,然后解析XML文档中的各个元素,如import、bean等。对于bean元素,会解析其name、id、alias,以及class属性等。如果允许覆盖,相同的bean定义会被覆盖...
Spring IoC(Inversion of Control,控制反转)容器是Spring框架的核心组件之一,用于管理对象的生命周期以及依赖关系。通过Spring IoC容器,开发者能够更加轻松地管理和配置Java应用中的各种组件。 #### 二、...
- **BeanFactory**:这是Spring中最基本的容器,它负责加载配置文件,解析Bean定义,然后根据这些定义实例化Bean。可以通过`XmlBeanFactory`类使用XML配置文件初始化一个BeanFactory。 - **ApplicationContext**:...
`spring-context-4.2.xsd`包含了一系列元素,如`beans`、`bean`、`import`、`alias`、`bean-definition`等,这些都是Spring配置中的关键组成部分。例如,`<beans>`元素是所有配置的根元素,`<bean>`元素用于定义一个...
默认命名空间下,还有`beans`用于指定环境、`alias`用于配置别名、`import`用于导入其他配置文件。 Bean的实例化过程大致分为以下几个步骤:解析XML配置文件,将Bean定义转换成BeanDefinition对象,然后创建Bean...
在Spring中,bean的别名允许我们为同一个bean定义多个名字,可以通过`@Component("alias1", "alias2")`或者在XML配置中使用`id`和`name`属性来设定。这在某些场景下非常有用,比如接口的实现类切换。关于bean的作用...
本文将详细解析Spring中XML配置文件的十二个最佳实践,主要关注前六个方法。 1. **避免使用自动绑定(Autowiring)** Spring的自动绑定功能允许框架通过类的自省自动注入依赖。虽然可以减少手动配置,但会导致配置...
此外,还有`<alias>`用于为bean创建别名,`<import>`引入其他配置文件,以及`<property>`用于设置bean的属性值等。 然而,随着Spring的发展,`spring-beans-3.1.xsd`在3.1版本中出现,引入了一些新特性以增强灵活性...
8. 使用`<import>`引入其他配置:当配置文件变得庞大时,可以将相关bean分组到单独的XML文件中,然后使用`<import>`标签导入这些文件,保持配置结构清晰。 9. 利用`<alias>`创建别名:为bean创建别名可以提供多个...
除了这些核心概念,Spring的XML配置还包括其他元素,如`<import>`引入其他配置文件,`<alias>`为bean定义别名,以及`<lookup-method>`和`<replaced-method>`来处理方法的动态代理等。XML配置提供了一种声明式的方式...
当有多个相同类型的bean时,`<qualifier>`标签可以帮助指定注入哪个特定的bean。 10. **使用`<lookup-method>`和`<factory-method>`**: 这两个元素允许在运行时动态创建bean,而不是在配置时静态定义。这对于...
mybatis实战教程mybatis in action之五与spring3集成附源码 mybatis实战教程mybatis in action之六与Spring MVC 的集成 mybatis实战教程mybatis in action之七实现mybatis分页源码下载 mybatis实战教程mybatis in ...
引入了如`<import>`、`<alias>`、`<bean>`标签的简写形式等,使得配置文件更易读、更易于维护。 5. **Annotation-driven Configuration**: 从Spring 2.5开始,Spring引入了注解驱动的配置,允许开发者在类或方法...
通过在主配置文件中使用`<import>`标签导入其他配置文件,可以有效地组织和管理不同的配置信息,使得每个文件专注于特定的功能模块。例如: ```xml <import resource="billingServices.xml"/> <import resource=...
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> </bean> <!-- 开启事务注解 --> <!-- 扫描Dao接口所在的包 --> ``` 这里主要包括数据源...