spring 源码-beans(一)

 2019-10-17 21:46  阅读(726)
文章分类:Spring boot

1 spring-beans概要

spring-beans 是sping两大核心组件之一,另一核心组件为spring-context,
两者也都依赖spring-core包,但spring-context依赖spring-beans实现;
spring-beans 是ioc实现的核心,spring其它相关组件的实现都有依赖于它;
20191017100120\_1.png

2 测试demo分析

从常用到的XmlBeanfactory开始分析

public class Test1 {
      public static void main(String[] args){
        ClassPathResource classPathResource = new ClassPathResource("spring-beans.xml");
        BeanFactory factory = new XmlBeanFactory(classPathResource);
        Object testBean = factory.getBean("testBean");
        System.out.println(testBean);
      }
    }

先查看XmlBeanfactory继承关系图,观察其有什么功能,再进入步深入源码分析。
20191017100120\_2.png

public class XmlBeanFactory extends DefaultListableBeanFactory {
        //根据名称,可以猜测,该类的作用是读取xml定义的bean
        private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);

        /** * Create a new XmlBeanFactory with the given resource, * which must be parsable using DOM. * @param resource XML resource to load bean definitions from * @throws BeansException in case of loading or parsing errors */
        public XmlBeanFactory(Resource resource) throws BeansException {
            this(resource, null);
        }

        /** * Create a new XmlBeanFactory with the given input stream, * which must be parsable using DOM. * @param resource XML resource to load bean definitions from * @param parentBeanFactory parent bean factory * @throws BeansException in case of loading or parsing errors */
        public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
            super(parentBeanFactory);
            this.reader.loadBeanDefinitions(resource);
        }

    }

上面的类非常简单,主要作用是DefaultListBeanFactory去实现了,上面可以看到beanfactory已经被XmlBeandefinitionReader 引用,接下来看XmlBeandefinitonReader把xml加载到解释成beandefinition然后再注册到beanfactory里;

3 XmlBeandefinitionReader加载xml配置文件

@Override
        public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
            return loadBeanDefinitions(new EncodedResource(resource));
        }

        /** * Load bean definitions from the specified XML file. * @param encodedResource the resource descriptor for the XML file, * allowing to specify an encoding to use for parsing the file * @return the number of bean definitions found * @throws BeanDefinitionStoreException in case of loading or parsing errors */
        public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
            Assert.notNull(encodedResource, "EncodedResource must not be null");
            if (logger.isInfoEnabled()) {
                logger.info("Loading XML bean definitions from " + encodedResource.getResource());
            }
            //本地线程存储当前加载的xml资源
            Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
            if (currentResources == null) {
                currentResources = new HashSet<EncodedResource>(4);
                this.resourcesCurrentlyBeingLoaded.set(currentResources);
            }
            if (!currentResources.add(encodedResource)) {
                throw new BeanDefinitionStoreException(
                        "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
            }
            try {

                InputStream inputStream = encodedResource.getResource().getInputStream();
                try { //xml文件转为输入流
                    InputSource inputSource = new InputSource(inputStream);
                    if (encodedResource.getEncoding() != null) {
                        inputSource.setEncoding(encodedResource.getEncoding());
                    }
                    //加载读取流资源
                    return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
                }
                finally {
                    inputStream.close();
                }
            }
            catch (IOException ex) {
                throw new BeanDefinitionStoreException(
                        "IOException parsing XML document from " + encodedResource.getResource(), ex);
            }
            finally {
                currentResources.remove(encodedResource);
                if (currentResources.isEmpty()) {
                    this.resourcesCurrentlyBeingLoaded.remove();
                }
            }
        }

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
        throws BeanDefinitionStoreException {
        try {   //xml转为doc
                Document doc = doLoadDocument(inputSource, resource);
                //接下来就是把xml标签元素解出来,并封装成beandefinition
                return registerBeanDefinitions(doc, resource);
            }
            catch (BeanDefinitionStoreException ex) {
                throw ex;
            }
        }

4 解释xml

//这段代码非常简单无必解释
        public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
            BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
            int countBefore = getRegistry().getBeanDefinitionCount();
            documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
            return getRegistry().getBeanDefinitionCount() - countBefore;
        }

接下来是对BeanDefinitionDocumentReader的分析了

public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
            this.readerContext = readerContext;
            logger.debug("Loading bean definitions");
            Element root = doc.getDocumentElement();
            doRegisterBeanDefinitions(root);
        }
        /** * Register each bean definition within the given root {@code <beans/>} element. */
        protected void doRegisterBeanDefinitions(Element root) {
            //创建代理解释器
            BeanDefinitionParserDelegate parent = this.delegate;
            this.delegate = createDelegate(getReaderContext(), root, parent);
            //处理不同profile相关
            if (this.delegate.isDefaultNamespace(root)) {
                String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
                if (StringUtils.hasText(profileSpec)) {
                    String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
                            profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
                    if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                        if (logger.isInfoEnabled()) {
                            logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
                                    "] not matching: " + getReaderContext().getResource());
                        }
                        return;
                    }
                }
            }
            //空的,由子类去实现
            preProcessXml(root);
            parseBeanDefinitions(root, this.delegate);
            //空的,由子类去实现
            postProcessXml(root);
            this.delegate = parent;
        }
         */
        protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
            //默认的命名空间http://www.springframework.org/schema/beans
            if (delegate.isDefaultNamespace(root)) {
                NodeList nl = root.getChildNodes();
                for (int i = 0; i < nl.getLength(); i++) {
                    Node node = nl.item(i);
                    if (node instanceof Element) {
                        Element ele = (Element) node;
                        if (delegate.isDefaultNamespace(ele)) {
                            //为spring默认标签
                            parseDefaultElement(ele, delegate);
                        }
                        else {
                            //自定义标签,深入为自定义标签解释器处理
                            delegate.parseCustomElement(ele);
                        }
                    }
                }
            }
            else {
            //自定义标签,深入为自定义标签解释器处理
                delegate.parseCustomElement(root);
            }
        }

5 spring默认标签解释

DefaultBeanDefinitionDocumentReader

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
            //import标签 
            if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
                //处理import,xml文件
                importBeanDefinitionResource(ele);
            }
            //alias标签
            else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
                //处理别bean的别名
                processAliasRegistration(ele);
            }
            //bean标签
            else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
                //解释成beandefiniton
                processBeanDefinition(ele, delegate);
            }
            //beans标签
            else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
                // recurse beans标签,再进入子元素解释
                doRegisterBeanDefinitions(ele);
            }
        }

        protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
        //通过BeanDefinitionParserDelegate 解释成 相应用的 beandefinition 现封装一层成beandefinitionholder
            BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
            if (bdHolder != null) {
                bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
                try {
                    // Register the final decorated instance.
    //把上面解释得到的beandefinition注册到beanfactory里 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
                }
                catch (BeanDefinitionStoreException ex) {
                    getReaderContext().error("Failed to register bean definition with name '" +
                            bdHolder.getBeanName() + "'", ele, ex);
                }
                // Send registration event.
                getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
            }
        }

BeanDefinitionParserDelegate

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
            //获取id属性值
            String id = ele.getAttribute(ID_ATTRIBUTE);
            //获取名称属性值,可能有多个名称
            String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

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

            String beanName = id;
            if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
                beanName = aliases.remove(0);
                if (logger.isDebugEnabled()) {
                    logger.debug("No XML 'id' specified - using '" + beanName +
                            "' as bean name and " + aliases + " as aliases");
                }
            }
            //检测名称的唯一性
            if (containingBean == null) {
                checkNameUniqueness(beanName, aliases, ele);
            }
            //开始具体的属性解释,并创建对应的beandefinition
            AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
            if (beanDefinition != null) {
                if (!StringUtils.hasText(beanName)) {
                    try {
                        if (containingBean != null) {
                            beanName = BeanDefinitionReaderUtils.generateBeanName(
                                    beanDefinition, this.readerContext.getRegistry(), true);
                        }
                        else {
                            beanName = this.readerContext.generateBeanName(beanDefinition);
                            // Register an alias for the plain bean class name, if still possible,
                            // if the generator returned the class name plus a suffix.
                            // This is expected for Spring 1.2/2.0 backwards compatibility.
                            String beanClassName = beanDefinition.getBeanClassName();
                            if (beanClassName != null &&
                                    beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
                                    !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
                                aliases.add(beanClassName);
                            }
                        }
                        if (logger.isDebugEnabled()) {
                            logger.debug("Neither XML 'id' nor 'name' specified - " +
                                    "using generated bean name [" + beanName + "]");
                        }
                    }
                    catch (Exception ex) {
                        error(ex.getMessage(), ele);
                        return null;
                    }
                }
                String[] aliasesArray = StringUtils.toStringArray(aliases);
                return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
            }

            return null;
        }
        public AbstractBeanDefinition parseBeanDefinitionElement(
                Element ele, String beanName, BeanDefinition containingBean) {

            this.parseState.push(new BeanEntry(beanName));

            String className = null;
            //解释class属性
            if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
                className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
            }

            try {//解释parent属性
                String parent = null;
                if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
                    parent = ele.getAttribute(PARENT_ATTRIBUTE);
                }
                AbstractBeanDefinition bd = createBeanDefinition(className, parent);
                //解释其余所有属笥
                parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
                bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
                //解释meta属性
                parseMetaElements(ele, bd);
                //复写属性
                parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
                //替换子元素
                parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
                //处理构造,以便生成实例
                parseConstructorArgElements(ele, bd);
                //处理property 标签
                parsePropertyElements(ele, bd);
                parseQualifierElements(ele, bd);

                bd.setResource(this.readerContext.getResource());
                bd.setSource(extractSource(ele));

                return bd;
            }
            catch (ClassNotFoundException ex) {
                error("Bean class [" + className + "] not found", ele, ex);
            }
            catch (NoClassDefFoundError err) {
                error("Class that bean class [" + className + "] depends on not found", ele, err);
            }
            catch (Throwable ex) {
                error("Unexpected failure during bean definition parsing", ele, ex);
            }
            finally {
                this.parseState.pop();
            }

            return null;
        }

6 自定义标签解释

上面说到的只是默认标签的解释,下面接着自定义标签解释分析
BeanDefinitionParserDelegate

public BeanDefinition parseCustomElement(Element ele) {
            return parseCustomElement(ele, null);
        }

        public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
            //获取取自定义标签的命名空间uri,能便通过其它对应的命名空间处理器
            String namespaceUri = getNamespaceURI(ele);
            //获取命名空间处理器
            NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
            if (handler == null) {
                error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
                return null;
            }
            //由自定义命名空间处理去解释自定议标签,具体如何释待分析context去分解
            return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
        }

NamespaceHandlerSupport

@Override
        public BeanDefinition parse(Element element, ParserContext parserContext) {
            return findParserForElement(element, parserContext).parse(element, parserContext);
        }

        /** * Locates the {@link BeanDefinitionParser} from the register implementations using * the local name of the supplied {@link Element}. */
        private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
            //据元素名,把到对应的标签解释器
            String localName = parserContext.getDelegate().getLocalName(element);
            BeanDefinitionParser parser = this.parsers.get(localName);
            if (parser == null) {
                parserContext.getReaderContext().fatal(
                        "Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
            }
            return parser;
        }

来源:[]()

点赞(0)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> spring 源码-beans(一)

相关推荐