您的位置:首页 > 编程语言 > Java开发

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

2008-09-22 21:29 459 查看
前面几小节,我们一直都在分析spring的一些基本类,这一节我们来看看XmlBeanFactory这个正主,ioc工厂;
public class XmlBeanFactory extends DefaultListableBeanFactory {

    private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);

    
    public XmlBeanFactory(Resource resource) throws BeansException {
        this(resource, null);
    }

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

}

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

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



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

        this.beanDefinitionReader = reader;
        this.resource = resource;

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

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

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

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

 preProcessXml(root){};

 postProcessXml(root){};

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

protected BeanDefinitionHolder parseBeanDefinitionElement(Element ele, boolean isInnerBean)
            throws BeanDefinitionStoreException {

        String id = ele.getAttribute(ID_ATTRIBUTE);
        String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

        List aliases = new ArrayList();
        if (StringUtils.hasLength(nameAttr)) {
            String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, BEAN_NAME_DELIMITERS);
            aliases.addAll(Arrays.asList(nameArr));
        }

        String beanName = id;
        if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
            beanName = (String) aliases.remove(0);
            if (logger.isDebugEnabled()) {
                logger.debug("No XML 'id' specified - using '" + beanName +
                        "' as bean name and " + aliases + " as aliases");
            }
        }

        BeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName);

        if (!StringUtils.hasText(beanName) && beanDefinition instanceof AbstractBeanDefinition) {
            beanName = BeanDefinitionReaderUtils.generateBeanName(
                    (AbstractBeanDefinition) beanDefinition, this.beanDefinitionReader.getBeanFactory(), isInnerBean);
            if (logger.isDebugEnabled()) {
                logger.debug("Neither XML 'id' nor 'name' specified - " +
                        "using generated bean name [" + beanName + "]");
            }
        }

        String[] aliasesArray = StringUtils.toStringArray(aliases);
        return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
    }

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

protected BeanDefinition parseBeanDefinitionElement(Element ele, String beanName)
            throws BeanDefinitionStoreException {

        String className = null;
        if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
            className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
        }
        String parent = null;
        if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
            parent = ele.getAttribute(PARENT_ATTRIBUTE);
        }

        try {
            ConstructorArgumentValues cargs = parseConstructorArgElements(ele, beanName);
            MutablePropertyValues pvs = parsePropertyElements(ele, beanName);

            AbstractBeanDefinition bd = BeanDefinitionReaderUtils.createBeanDefinition(
                    className, parent, cargs, pvs, getBeanDefinitionReader().getBeanClassLoader());

            if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
                String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
                bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, BEAN_NAME_DELIMITERS));
            }

            if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
                bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
            }
            if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
                bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
            }

            String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE);
            if (DEFAULT_VALUE.equals(dependencyCheck)) {
                dependencyCheck = getDefaultDependencyCheck();
            }
            bd.setDependencyCheck(getDependencyCheck(dependencyCheck));

            String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
            if (DEFAULT_VALUE.equals(autowire)) {
                autowire = getDefaultAutowire();
            }
            bd.setAutowireMode(getAutowireMode(autowire));

            if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
                String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
                if (!"".equals(initMethodName)) {
                    bd.setInitMethodName(initMethodName);
                }
            }
            else {
                if (getDefaultInitMethod() != null) {
                    bd.setInitMethodName(getDefaultInitMethod());
                    bd.setEnforceInitMethod(false);
                }
            }

            if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
                String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
                if (!"".equals(destroyMethodName)) {
                    bd.setDestroyMethodName(destroyMethodName);
                }
            }
            else {
                if (getDefaultDestroyMethod() != null) {
                    bd.setDestroyMethodName(getDefaultDestroyMethod());
                    bd.setEnforceDestroyMethod(false);
                }
            }

            parseLookupOverrideSubElements(ele, beanName, bd.getMethodOverrides());
            parseReplacedMethodSubElements(ele, beanName, bd.getMethodOverrides());

            bd.setResourceDescription(getResource().getDescription());

            if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
                bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
            }

            if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
                bd.setSingleton(TRUE_VALUE.equals(ele.getAttribute(SINGLETON_ATTRIBUTE)));
            }

            String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
            if (DEFAULT_VALUE.equals(lazyInit) && bd.isSingleton()) {
                // Just apply default to singletons, as lazy-init has no meaning for prototypes.
                lazyInit = getDefaultLazyInit();
            }
            bd.setLazyInit(TRUE_VALUE.equals(lazyInit));

            return bd;
        }

        catch (BeanDefinitionStoreException ex) {
            throw ex;
        }
        catch (ClassNotFoundException ex) {
            throw new BeanDefinitionStoreException(
                    getResource(), beanName, "Bean class [" + className + "] not found", ex);
        }
        catch (NoClassDefFoundError err) {
            throw new BeanDefinitionStoreException(
                    getResource(), beanName, "Class that bean class [" + className + "] depends on not found", err);
        }
        catch (Throwable ex) {
            throw new BeanDefinitionStoreException(
                    getResource(), beanName, "Unexpected failure during bean definition parsing", ex);
        }
    }

   

上述代码详细的解析了各种元素,并且把他set到BeanDefinition中去;

最后:public static void registerBeanDefinition(
            BeanDefinitionHolder bdHolder, BeanDefinitionRegistry beanFactory) throws BeanDefinitionStoreException {

        // Register bean definition under primary name.
        beanFactory.registerBeanDefinition(bdHolder.getBeanName(), bdHolder.getBeanDefinition());

        // Register aliases for bean name, if any.
        if (bdHolder.getAliases() != null) {
            for (int i = 0; i < bdHolder.getAliases().length; i++) {
                beanFactory.registerAlias(bdHolder.getBeanName(), bdHolder.getAliases()[i]);
            }
        }
    }
很荣幸的,该BeanDefinition被加载到该BeanFactory的beanDefinitions的map中,被用来在getBean()中转换为Bean;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息