Spring源代码分析(7)---XmlBeanFactory(迟来的正主)


前面几小节,我们一直都在分析spring的一些基本类,这一节我们来看看XmlBeanFactory这个正主,ioc工厂;
  1. public class XmlBeanFactory extends DefaultListableBeanFactory {

  2.     private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);


  3.     
  4.     public XmlBeanFactory(Resource resource) throws BeansException {
  5.         this(resource, null);
  6.     }


  7.     public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
  8.         super(parentBeanFactory);
  9.         this.reader.loadBeanDefinitions(resource);
  10.     }

  11. }

reader.loadBeanDefinitions(resource);可见,从外部加载xml配置文件,XmlBeanFactory是通过委托给 XmlBeanDefinitionReader做的,其他都是 DefaultListableBeanFactory 继承而来;

那么,我们重点来分析一些xml文件是如何把配置加载到BeanFactory中的:






  1.     public int registerBeanDefinitions(Document doc, Resource resource) throws BeansException {
  2.         XmlBeanDefinitionParser parser =
  3.                 (XmlBeanDefinitionParser) BeanUtils.instantiateClass(this.parserClass);
  4.         return parser.registerBeanDefinitions(this, doc, resource);
  5.     }
registerBeanDefinitions是reader是通过SAXBuilder把外部xml转换成为了Document,然后用BeanDefinition解析器来解析这个documeng文档;
  1. public int registerBeanDefinitions(BeanDefinitionReader reader, Document doc, Resource resource)
  2.             throws BeanDefinitionStoreException {

  3.         this.beanDefinitionReader = reader;
  4.         this.resource = resource;

  5.         logger.debug("Loading bean definitions");
  6.         Element root = doc.getDocumentElement();

  7.         initDefaults(root);
  8.         if (logger.isDebugEnabled()) {
  9.             logger.debug("Default lazy init '" + getDefaultLazyInit() + "'");
  10.             logger.debug("Default autowire '" + getDefaultAutowire() + "'");
  11.             logger.debug("Default dependency check '" + getDefaultDependencyCheck() + "'");
  12.         }

  13.         preProcessXml(root);
  14.         int beanDefinitionCount = parseBeanDefinitions(root);
  15.         if (logger.isDebugEnabled()) {
  16.             logger.debug("Found " + beanDefinitionCount + " <bean> elements in " + resource);
  17.         }
  18.         postProcessXml(root);

  19.         return beanDefinitionCount;
  20.     }
registerBeanDefinitions方法从root元素开始处理整个document,在这里我们可以在一次看见spring给我们留出来的钩子方法,典型的模板方法的应用;

 preProcessXml(root){};

 postProcessXml(root){};



  1. protected int parseBeanDefinitions(Element root) throws BeanDefinitionStoreException {
  2.         NodeList nl = root.getChildNodes();
  3.         int beanDefinitionCount = 0;
  4.         for (int i = 0; i < nl.getLength(); i++) {
  5.             Node node = nl.item(i);
  6.             if (node instanceof Element) {
  7.                 Element ele = (Element) node;
  8.                 if (IMPORT_ELEMENT.equals(node.getNodeName())) {
  9.                     importBeanDefinitionResource(ele);
  10.                 }
  11.                 else if (ALIAS_ELEMENT.equals(node.getNodeName())) {
  12.                     String name = ele.getAttribute(NAME_ATTRIBUTE);
  13.                     String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
  14.                     this.beanDefinitionReader.getBeanFactory().registerAlias(name, alias);
  15.                 }
  16.                 else if (BEAN_ELEMENT.equals(node.getNodeName())) {
  17.                     beanDefinitionCount++;
  18.                     BeanDefinitionHolder bdHolder = parseBeanDefinitionElement(ele, false);
  19.                     BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.beanDefinitionReader.getBeanFactory());
  20.                 }
  21.             }
  22.         }
  23.         return beanDefinitionCount;
  24.     }
parseBeanDefinitions方法中,我们开始遍历整个文档的节点,处理每个节点;并且从节点的名字,我们可以判断出三种节点,一种是<import>一种是<alias>一种是<bean>
BeanDefinitionHolder 是一个含有BeanDefinition和Bean name的存储器,我们主要来看一下spring如何从bean element 构造出BeanDefinition();



  1. protected BeanDefinitionHolder parseBeanDefinitionElement(Element ele, boolean isInnerBean)
  2.             throws BeanDefinitionStoreException {
  3.         String id = ele.getAttribute(ID_ATTRIBUTE);
  4.         String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
  5.         List aliases = new ArrayList();
  6.         if (StringUtils.hasLength(nameAttr)) {
  7.             String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, BEAN_NAME_DELIMITERS);
  8.             aliases.addAll(Arrays.asList(nameArr));
  9.         }
  10.         String beanName = id;
  11.         if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
  12.             beanName = (String) aliases.remove(0);
  13.             if (logger.isDebugEnabled()) {
  14.                 logger.debug("No XML 'id' specified - using '" + beanName +
  15.                         "' as bean name and " + aliases + " as aliases");
  16.             }
  17.         }
  18.         BeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName);
  19.         if (!StringUtils.hasText(beanName) && beanDefinition instanceof AbstractBeanDefinition) {
  20.             beanName = BeanDefinitionReaderUtils.generateBeanName(
  21.                     (AbstractBeanDefinition) beanDefinition, this.beanDefinitionReader.getBeanFactory(), isInnerBean);
  22.             if (logger.isDebugEnabled()) {
  23.                 logger.debug("Neither XML 'id' nor 'name' specified - " +
  24.                         "using generated bean name [" + beanName + "]");
  25.             }
  26.         }
  27.         String[] aliasesArray = StringUtils.toStringArray(aliases);
  28.         return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
  29.     }

主要是获取alias,把名字用.;分开,解析成为别名;


  1. protected BeanDefinition parseBeanDefinitionElement(Element ele, String beanName)
  2.             throws BeanDefinitionStoreException {
  3.         String className = null;
  4.         if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
  5.             className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
  6.         }
  7.         String parent = null;
  8.         if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
  9.             parent = ele.getAttribute(PARENT_ATTRIBUTE);
  10.         }
  11.         try {
  12.             ConstructorArgumentValues cargs = parseConstructorArgElements(ele, beanName);
  13.             MutablePropertyValues pvs = parsePropertyElements(ele, beanName);
  14.             AbstractBeanDefinition bd = BeanDefinitionReaderUtils.createBeanDefinition(
  15.                     className, parent, cargs, pvs, getBeanDefinitionReader().getBeanClassLoader());
  16.             if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
  17.                 String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
  18.                 bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, BEAN_NAME_DELIMITERS));
  19.             }
  20.             if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
  21.                 bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
  22.             }
  23.             if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
  24.                 bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
  25.             }
  26.             String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE);
  27.             if (DEFAULT_VALUE.equals(dependencyCheck)) {
  28.                 dependencyCheck = getDefaultDependencyCheck();
  29.             }
  30.             bd.setDependencyCheck(getDependencyCheck(dependencyCheck));
  31.             String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
  32.             if (DEFAULT_VALUE.equals(autowire)) {
  33.                 autowire = getDefaultAutowire();
  34.             }
  35.             bd.setAutowireMode(getAutowireMode(autowire));
  36.             if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
  37.                 String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
  38.                 if (!"".equals(initMethodName)) {
  39.                     bd.setInitMethodName(initMethodName);
  40.                 }
  41.             }
  42.             else {
  43.                 if (getDefaultInitMethod() != null) {
  44.                     bd.setInitMethodName(getDefaultInitMethod());
  45.                     bd.setEnforceInitMethod(false);
  46.                 }
  47.             }
  48.             if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
  49.                 String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
  50.                 if (!"".equals(destroyMethodName)) {
  51.                     bd.setDestroyMethodName(destroyMethodName);
  52.                 }
  53.             }
  54.             else {
  55.                 if (getDefaultDestroyMethod() != null) {
  56.                     bd.setDestroyMethodName(getDefaultDestroyMethod());
  57.                     bd.setEnforceDestroyMethod(false);
  58.                 }
  59.             }
  60.             parseLookupOverrideSubElements(ele, beanName, bd.getMethodOverrides());
  61.             parseReplacedMethodSubElements(ele, beanName, bd.getMethodOverrides());
  62.             bd.setResourceDescription(getResource().getDescription());
  63.             if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
  64.                 bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
  65.             }
  66.             if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
  67.                 bd.setSingleton(TRUE_VALUE.equals(ele.getAttribute(SINGLETON_ATTRIBUTE)));
  68.             }
  69.             String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
  70.             if (DEFAULT_VALUE.equals(lazyInit) && bd.isSingleton()) {
  71.                 // Just apply default to singletons, as lazy-init has no meaning for prototypes.
  72.                 lazyInit = getDefaultLazyInit();
  73.             }
  74.             bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
  75.             return bd;
  76.         }
  77.         catch (BeanDefinitionStoreException ex) {
  78.             throw ex;
  79.         }
  80.         catch (ClassNotFoundException ex) {
  81.             throw new BeanDefinitionStoreException(
  82.                     getResource(), beanName, "Bean class [" + className + "] not found", ex);
  83.         }
  84.         catch (NoClassDefFoundError err) {
  85.             throw new BeanDefinitionStoreException(
  86.                     getResource(), beanName, "Class that bean class [" + className + "] depends on not found", err);
  87.         }
  88.         catch (Throwable ex) {
  89.             throw new BeanDefinitionStoreException(
  90.                     getResource(), beanName, "Unexpected failure during bean definition parsing", ex);
  91.         }
  92.     }
  93.    
上述代码详细的解析了各种元素,并且把他set到BeanDefinition中去;

最后:
  1. public static void registerBeanDefinition(
  2.             BeanDefinitionHolder bdHolder, BeanDefinitionRegistry beanFactory) throws BeanDefinitionStoreException {
  3.         // Register bean definition under primary name.
  4.         beanFactory.registerBeanDefinition(bdHolder.getBeanName(), bdHolder.getBeanDefinition());
  5.         // Register aliases for bean name, if any.
  6.         if (bdHolder.getAliases() != null) {
  7.             for (int i = 0; i < bdHolder.getAliases().length; i++) {
  8.                 beanFactory.registerAlias(bdHolder.getBeanName(), bdHolder.getAliases()[i]);
  9.             }
  10.         }
  11.     }
很荣幸的,该BeanDefinition被加载到该BeanFactory的beanDefinitions的map中,被用来在getBean()中转换为Bean;

你可能感兴趣的:(Spring源代码分析(7)---XmlBeanFactory(迟来的正主))