Spring源码版本:4.3.23.RELEASE

一、加载XML配置

通过XML配置创建Spring,创建入口是使用org.springframework.context.support.ClassPathXmlApplicationContext类,创建容器的代码如下:

 package hello;

 import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class HelloWorld
{
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println(context.getBean("hello.Dog", Dog.class).name);
System.out.println(context.getBean("hello.Dog#0", Dog.class).name);
}
} class Dog {
String name = "PiPi";
}
 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean class="hello.Dog"/> </beans>

1.1 如果bean没有配置id或name属性,那Spring会取class属性值(也就是全限定类名)加#index(index为bean对象在容器里的序号)作为name,取类全限定名作为别名aliases。具体看下面源码:

org/springframework/beans/factory/xml/BeanDefinitionParserDelegate.java#parseBeanDefinitionElement

     /**
* Parses the supplied {@code <bean>} element. May return {@code null}
* if there were errors during parse. Errors are reported to the
* {@link org.springframework.beans.factory.parsing.ProblemReporter}.
*/
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
String id = ele.getAttribute(ID_ATTRIBUTE);
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); List<String> aliases = new ArrayList<String>();
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
} String beanName = id;
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
beanName = aliases.remove(0);
if (logger.isDebugEnabled()) {
logger.debug("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
} if (containingBean == null) {
checkNameUniqueness(beanName, aliases, ele);
} AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
beanName = this.readerContext.generateBeanName(beanDefinition); //获取到的bean名称为com.example.Hello#0这样的格式,#后面的数字为该类对象在进程中的编号。
// 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(); //获取class属性配置的bean的类名(全限定类名)
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName); //使用全限定类名作为别名
}
}
if (logger.isDebugEnabled()) {
logger.debug("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); //创建bean定义对象
} return null;
}

1.2 Bean的定义加载到一个ConcurrentHashMap,key为bean名称,value为org.springframework.beans.factory.config.BeanDefinition:

org.springframework.beans.factory.support.DefaultListableBeanFactory#beanDefinitionMap

    /** Map of bean definition objects, keyed by bean name */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);

org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition

     //---------------------------------------------------------------------
// Implementation of BeanDefinitionRegistry interface
//--------------------------------------------------------------------- @Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException { Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null"); if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
} BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + existingDefinition + "] bound.");
}
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isWarnEnabled()) {
logger.warn("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(existingDefinition)) {
if (logger.isInfoEnabled()) {
logger.info("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
} if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}

最新文章

  1. ajax参数设置略解
  2. BI领导驾驶舱的功能特点
  3. [FFmpeg] ffmpeg参数详解
  4. LevelDB(v1.3) 源码阅读之 Slice
  5. jQuery.validate API
  6. Jsp中三种注释
  7. mysql查询一天,查询一周,查询一个月的数据【转】
  8. JavaScript中的內定物件與函式: arguments, callee, caller, this, apply(), call()
  9. memcached-session-manager的一些理解
  10. Windows下一个SlikSVN使用
  11. YII 1.0 验证码
  12. HDU1392(凸包)
  13. 在CentOS下安装Git
  14. python基础学习(五)while循环语句
  15. PHP自动加载SPL的四种处理方式
  16. OpenGL + VS2015 + Windows10配置
  17. notepad++插件实现json、xml格式化
  18. linux定时任务-crontab
  19. 用户管理和FTP服务配置
  20. [POJ3370]&amp;[HDU1808]Halloween treats 题解(鸽巢原理)

热门文章

  1. 51Nod - 1304 :字符串的相似度 (裸的扩展KMP)
  2. 利用openssl进行base64的编码与解码
  3. spark运行模式之一:Spark的local模式安装部署
  4. salt api
  5. 修改Linux内核参数提高Nginx服务器在高的时候的性能
  6. linq Foreach
  7. CF-798A
  8. java读取文件:二进制文件
  9. 网络编程-TCP连接-readLine
  10. win10+PHP 安装redis