• Spring源码:Spring IoC容器加载过程(2)


     Spring源码版本:4.3.23.RELEASE

    一、加载XML配置

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

     1 package hello;
     2 
     3 import org.springframework.context.ApplicationContext;
     4 import org.springframework.context.support.ClassPathXmlApplicationContext;
     5 
     6 public class HelloWorld
     7 {
     8     public static void main(String[] args) {
     9         ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    10         System.out.println(context.getBean("hello.Dog", Dog.class).name);
    11         System.out.println(context.getBean("hello.Dog#0", Dog.class).name);
    12     }
    13 }
    14 
    15 class Dog {
    16     String name = "PiPi";
    17 }
    1 <?xml version="1.0" encoding="UTF-8"?>
    2 <beans xmlns="http://www.springframework.org/schema/beans"
    3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    5 
    6     <bean class="hello.Dog"/>
    7 
    8 </beans>

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

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

     1     /**
     2      * Parses the supplied {@code <bean>} element. May return {@code null}
     3      * if there were errors during parse. Errors are reported to the
     4      * {@link org.springframework.beans.factory.parsing.ProblemReporter}.
     5      */
     6     public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
     7         String id = ele.getAttribute(ID_ATTRIBUTE);
     8         String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
     9 
    10         List<String> aliases = new ArrayList<String>();
    11         if (StringUtils.hasLength(nameAttr)) {
    12             String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
    13             aliases.addAll(Arrays.asList(nameArr));
    14         }
    15 
    16         String beanName = id;
    17         if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
    18             beanName = aliases.remove(0);
    19             if (logger.isDebugEnabled()) {
    20                 logger.debug("No XML 'id' specified - using '" + beanName +
    21                         "' as bean name and " + aliases + " as aliases");
    22             }
    23         }
    24 
    25         if (containingBean == null) {
    26             checkNameUniqueness(beanName, aliases, ele);
    27         }
    28 
    29         AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
    30         if (beanDefinition != null) {
    31             if (!StringUtils.hasText(beanName)) {
    32                 try {
    33                     if (containingBean != null) {
    34                         beanName = BeanDefinitionReaderUtils.generateBeanName(
    35                                 beanDefinition, this.readerContext.getRegistry(), true);
    36                     }
    37                     else {
    38                         beanName = this.readerContext.generateBeanName(beanDefinition);  //获取到的bean名称为com.example.Hello#0这样的格式,#后面的数字为该类对象在进程中的编号。
    39                         // Register an alias for the plain bean class name, if still possible,
    40                         // if the generator returned the class name plus a suffix.
    41                         // This is expected for Spring 1.2/2.0 backwards compatibility.
    42                         String beanClassName = beanDefinition.getBeanClassName(); //获取class属性配置的bean的类名(全限定类名)
    43                         if (beanClassName != null &&
    44                                 beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
    45                                 !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
    46                             aliases.add(beanClassName);  //使用全限定类名作为别名
    47                         }
    48                     }
    49                     if (logger.isDebugEnabled()) {
    50                         logger.debug("Neither XML 'id' nor 'name' specified - " +
    51                                 "using generated bean name [" + beanName + "]");
    52                     }
    53                 }
    54                 catch (Exception ex) {
    55                     error(ex.getMessage(), ele);
    56                     return null;
    57                 }
    58             }
    59             String[] aliasesArray = StringUtils.toStringArray(aliases);
    60             return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);  //创建bean定义对象
    61         }
    62 
    63         return null;
    64     }

    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

     1     //---------------------------------------------------------------------
     2     // Implementation of BeanDefinitionRegistry interface
     3     //---------------------------------------------------------------------
     4 
     5     @Override
     6     public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
     7             throws BeanDefinitionStoreException {
     8 
     9         Assert.hasText(beanName, "Bean name must not be empty");
    10         Assert.notNull(beanDefinition, "BeanDefinition must not be null");
    11 
    12         if (beanDefinition instanceof AbstractBeanDefinition) {
    13             try {
    14                 ((AbstractBeanDefinition) beanDefinition).validate();
    15             }
    16             catch (BeanDefinitionValidationException ex) {
    17                 throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
    18                         "Validation of bean definition failed", ex);
    19             }
    20         }
    21 
    22         BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
    23         if (existingDefinition != null) {
    24             if (!isAllowBeanDefinitionOverriding()) {
    25                 throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
    26                         "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
    27                         "': There is already [" + existingDefinition + "] bound.");
    28             }
    29             else if (existingDefinition.getRole() < beanDefinition.getRole()) {
    30                 // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
    31                 if (logger.isWarnEnabled()) {
    32                     logger.warn("Overriding user-defined bean definition for bean '" + beanName +
    33                             "' with a framework-generated bean definition: replacing [" +
    34                             existingDefinition + "] with [" + beanDefinition + "]");
    35                 }
    36             }
    37             else if (!beanDefinition.equals(existingDefinition)) {
    38                 if (logger.isInfoEnabled()) {
    39                     logger.info("Overriding bean definition for bean '" + beanName +
    40                             "' with a different definition: replacing [" + existingDefinition +
    41                             "] with [" + beanDefinition + "]");
    42                 }
    43             }
    44             else {
    45                 if (logger.isDebugEnabled()) {
    46                     logger.debug("Overriding bean definition for bean '" + beanName +
    47                             "' with an equivalent definition: replacing [" + existingDefinition +
    48                             "] with [" + beanDefinition + "]");
    49                 }
    50             }
    51             this.beanDefinitionMap.put(beanName, beanDefinition);
    52         }
    53         else {
    54             if (hasBeanCreationStarted()) {
    55                 // Cannot modify startup-time collection elements anymore (for stable iteration)
    56                 synchronized (this.beanDefinitionMap) {
    57                     this.beanDefinitionMap.put(beanName, beanDefinition);
    58                     List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
    59                     updatedDefinitions.addAll(this.beanDefinitionNames);
    60                     updatedDefinitions.add(beanName);
    61                     this.beanDefinitionNames = updatedDefinitions;
    62                     if (this.manualSingletonNames.contains(beanName)) {
    63                         Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
    64                         updatedSingletons.remove(beanName);
    65                         this.manualSingletonNames = updatedSingletons;
    66                     }
    67                 }
    68             }
    69             else {
    70                 // Still in startup registration phase
    71                 this.beanDefinitionMap.put(beanName, beanDefinition);
    72                 this.beanDefinitionNames.add(beanName);
    73                 this.manualSingletonNames.remove(beanName);
    74             }
    75             this.frozenBeanDefinitionNames = null;
    76         }
    77 
    78         if (existingDefinition != null || containsSingleton(beanName)) {
    79             resetBeanDefinition(beanName);
    80         }
    81     }
  • 相关阅读:
    微软软件
    绘图软件安装出错解决方法
    Windows平台 Faster-RCNN 制作自己的数据集
    POJ2456 Agressive Cows
    P1030 求先序排列
    Luogu P2015二叉苹果树
    P2234 [HNOI2002]营业额统计
    Luogu P1347排序
    Luogu P1038神经网络
    Luogu P1006传纸条
  • 原文地址:https://www.cnblogs.com/burthughes/p/spring_2.html
Copyright © 2020-2023  润新知