• spring 加载bean过程源码简易解剖(转载)


    这一篇主要是讲用载入bean的过程。其实就是IOC.低调 低调。。 


    我把重要的都挑出来了。一步步往下看就明白spring载入bean.xml里面bean的原理 。 
    感觉像候杰的 MFC深入浅出,哈哈。 

    观看规则 

    接下 表示下一层代码。 
    接上 表示最近上面要调用的代码的详细部分。 

    1. public class XmlBeanFactory extends DefaultListableBeanFactory {  
    2.   
    3.         //新建一个bean分析器,把this注册到里面是因为,在分析器解析好一个bean时,可以立即用这个this里的注册方法去保存bean,往下看就明白。任何bean到最后都是保存在XmlBeanFactory里的(其实是DefaultListableBeanFactory)。   
    4.   
    5.     private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);  
    6.   
    7.     public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {  
    8.   
    9.         super(parentBeanFactory);  
    10.                 //载入xml文件  
    11.         this.reader.loadBeanDefinitions(resource); //往下->  
    12.     }  
    13. }  
    14.   
    15. public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {  
    16.      //接上  
    17.      public int loadBeanDefinitions(Resource resource) throws BeansException {  
    18.   
    19.         InputStream is = null;  
    20.   
    21.         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();  
    22.   
    23.         factory.setValidating(this.validating);  
    24.   
    25.         DocumentBuilder docBuilder = factory.newDocumentBuilder();  
    26.   
    27.         docBuilder.setErrorHandler(this.errorHandler);  
    28.   
    29.         if (this.entityResolver != null) {  
    30.             docBuilder.setEntityResolver(this.entityResolver);  
    31.         }  
    32.         is = resource.getInputStream();  
    33. //用Xerces解析xml,生成dom  
    34.         Document doc = docBuilder.parse(is);  
    35. //registerBeanDefinitions分析dom  
    36.         return registerBeanDefinitions(doc, resource); //往下  
    37.   
    38.     }  
    39.   
    40. //接上  
    41.         public int registerBeanDefinitions(Document doc, Resource resource) throws BeansException {  
    42.   
    43.         XmlBeanDefinitionParser parser = (XmlBeanDefinitionParser) BeanUtils.instantiateClass(this.parserClass);  
    44. //这个parserClass 是  DefaultXmlBeanDefinitionParser.class  
    45.         return parser.registerBeanDefinitions(this, doc, resource); //往下->  
    46.   
    47.     }  
    48.   
    49. }  
    50.   
    51. public class DefaultXmlBeanDefinitionParser implements XmlBeanDefinitionParser {  
    52. //明显就是bean.xml里面出现的很熟悉的标签,说明已经快到底层类了  
    53.          
    54.   
    55.     public static final String AUTOWIRE_BY_NAME_VALUE = "byName";  
    56.     public static final String AUTOWIRE_BY_TYPE_VALUE = "byType";  
    57.     public static final String DEFAULT_LAZY_INIT_ATTRIBUTE = "default-lazy-init";  
    58.     public static final String DEFAULT_DEPENDENCY_CHECK_ATTRIBUTE = "default-dependency-check";  
    59.     public static final String DEFAULT_AUTOWIRE_ATTRIBUTE = "default-autowire";  
    60.     public static final String NAME_ATTRIBUTE = "name";  
    61.     public static final String ALIAS_ATTRIBUTE = "alias";  
    62.     public static final String BEAN_ELEMENT = "bean";  
    63.     public static final String ID_ATTRIBUTE = "id";  
    64.     public static final String PARENT_ATTRIBUTE = "parent";  
    65.     public static final String CLASS_ATTRIBUTE = "class";  
    66.     public static final String SINGLETON_ATTRIBUTE = "singleton";  
    67.     public static final String LAZY_INIT_ATTRIBUTE = "lazy-init";  
    68.     public static final String AUTOWIRE_ATTRIBUTE = "autowire";  
    69.     //...  
    70.    //接上  
    71.    public int registerBeanDefinitions(BeanDefinitionReader reader, Document doc, Resource resource) throws BeanDefinitionStoreException {  
    72.   
    73.         this.beanDefinitionReader = reader;  
    74.         this.resource = resource;;  
    75.         Element root = doc.getDocumentElement();  
    76.         //...  
    77.   
    78. //这里准备开始正式解析bean  
    79.         int beanDefinitionCount = parseBeanDefinitions(root);//往下->  
    80. //这个beanDefinitionCount 就是解析出了多少个<bean></bean>  
    81.           
    82. //...  
    83.         return beanDefinitionCount;  
    84.     }  
    85.   
    86. protected int parseBeanDefinitions(Element root) throws BeanDefinitionStoreException {  
    87. //Xerces开始循环找<bean>标签  
    88.         NodeList nl = root.getChildNodes();  
    89.         int beanDefinitionCounter = 0;  
    90.         for (int i = 0; i < nl.getLength(); i++) {  
    91.             Node node = nl.item(i);  
    92.             if (node instanceof Element) {  
    93.                 Element ele = (Element) node;  
    94.                 if // ...  
    95. //..  
    96.                 else if (BEAN_ELEMENT.equals(node.getNodeName())) {//这里是重点,开始解析bean  
    97.                     beanDefinitionCounter++;  
    98. //分两步走,看下面详解。1.先把bean放到BeanDefinitionHolder  
    99.                     BeanDefinitionHolder bdHolder = parseBeanDefinitionElement(ele);//往下 1.->  
    100. //2.然后XmlBeanFactory去注册  
    101.                     BeanDefinitionReaderUtils.registerBeanDefinition(  
    102.                             bdHolder, this.beanDefinitionReader.getBeanFactory()); //往下 2. ->  
    103.                 }  
    104.             }  
    105.         }  
    106.         return beanDefinitionCounter;  
    107.     }  
    108.   
    109. //接上1. 哈哈,下面是第一步,是正常解析bean,在同一个类中  
    110. protected BeanDefinitionHolder parseBeanDefinitionElement(Element ele) throws BeanDefinitionStoreException {  
    111.         //...  
    112.                 //下面可以看到其实最底层的解析bean在同一个类的parseBeanDefinitionElement方法里。因为spring把bean封装成BeanDefinition 再把BeanDefinition 封装成BeanDefinitionHolder   
    113.   
    114.         BeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName);//往下  
    115.   
    116. //...  
    117.         return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);  
    118.     }  
    119.   
    120. //接上 , 这个方法很长,毕竟<bean>里attribute很多。  
    121.   protected BeanDefinition parseBeanDefinitionElement(Element ele, String beanName) throws BeanDefinitionStoreException {  
    122.         try {  
    123.                         //下面解析<bean>里的<property>,这个我不分析了。  
    124.             MutablePropertyValues pvs = parsePropertyElements(ele, beanName);  
    125.                         //将BeanDefinition封装成AbstractBeanDefinition   
    126.             AbstractBeanDefinition bd = BeanDefinitionReaderUtils.createBeanDefinition(  
    127.                     className, parent, cargs, pvs, this.beanDefinitionReader.getBeanClassLoader());  
    128.             //...         
    129.             return bd;  
    130.         }  
    131.         catch (/*...*/)  
    132.                    //...  
    133.   
    134.         }  
    135.     }  
    136.   
    137.   
    138. }  
    139. //bean解析部分到此结束。。。。  
    140.   
    141.   
    142. //接上2. 这里是第二部,注册部分,回到上面注释里的分两部走这里。  
    143. public class BeanDefinitionReaderUtils {  
    144.   public static void registerBeanDefinition(  
    145.             BeanDefinitionHolder bdHolder, BeanDefinitionRegistry beanFactory) throws BeansException {  
    146.   
    147.           
    148. //beanFactory就是XmlBeanFactory,其实是它的父类 DefaultListableBeanFactory在执行registerBeanDefinition  
    149.   
    150.   
    151.         beanFactory.registerBeanDefinition(bdHolder.getBeanName(), bdHolder.getBeanDefinition()); //往下  
    152. //...  
    153.     }  
    154.   
    155. }  
    156.   
    157. public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory  
    158.     implements ConfigurableListableBeanFactory, BeanDefinitionRegistry {  
    159.     
    160.     /** Whether to allow re-registration of a different definition with the same name */  
    161.     private boolean allowBeanDefinitionOverriding = true;  
    162.   
    163.     /** Map of bean definition objects, keyed by bean name */  
    164. //下面是真正藏bean的地方,其实是个Map,跟我预想的一样。  
    165.     private final Map beanDefinitionMap = new HashMap();  
    166. //下面List可能是给bean的名字做个索引,这是我的初步猜想。  
    167.     /** List of bean definition names, in registration order */  
    168.     private final List beanDefinitionNames = new ArrayList();  
    169.   //接上  
    170.   public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {  
    171. //...  
    172.   Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);  
    173.         if (oldBeanDefinition != null) {  
    174. //根据allowBeanDefinitionOverriding这个变量来决定在bean.xml里的bean万一有同名的情况下否覆盖,因为allowBeanDefinitionOverriding默认是true,所以覆盖。  
    175.             if (!this.allowBeanDefinitionOverriding) {  
    176.                 throw new BeanDefinitionStoreException(...);  
    177.             }  
    178.             else {  
    179.                 //...只用注释提醒相同bean将要被覆盖了  
    180.             }  
    181.         }  
    182.         else {  
    183.                         //索引List里加上这个bean名字  
    184.             this.beanDefinitionNames.add(beanName);  
    185.         }  
    186.                 //将bean藏在map里。用名字来索引。  
    187.         this.beanDefinitionMap.put(beanName, beanDefinition);  
    188.           
    189.     }  
    190. //...  
    191.   
    192. }  
    193. //结束  

    可以看到其实spring就是把bean.xml解析到一个map里。 

    转载路径:http://hzieept.iteye.com/blog/748283

  • 相关阅读:
    内存对齐
    类和对象
    C++ 各种继承方式的类内存布局
    静态变量static
    程序内存布局
    String类
    C++与C的区别
    命名空间
    C
    D
  • 原文地址:https://www.cnblogs.com/rainy-shurun/p/5092444.html
Copyright © 2020-2023  润新知