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     }

 

posted @ 2019-05-10 16:37  burthughes  阅读(473)  评论(0编辑  收藏  举报