zoukankan      html  css  js  c++  java
  • analyze spring framework source

    2B青年欢乐多啊,最近研究spring源码,做点笔记,欢迎继续补充, 持续更新

    接上一篇 1. Introduce how to import the Spring Framework sourcecode into an eclipse project

    一. 结构

    spring中bean管理设计到下面3个包

    image

    core 相当于一个工具类,bean包是对IOC的实现包,context是在bean的基础扩展功能

    IOC的实现原理简介

    简单实现

    复制代码
    package org.benson;
    
    import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
    import org.springframework.beans.factory.support.BeanDefinitionRegistry;
    import org.springframework.beans.factory.support.DefaultListableBeanFactory;
    import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
    import org.springframework.core.io.ClassPathResource;
    
    public class Test4DebugSpringIOC {
        ConfigurableListableBeanFactory beanFactory = new DefaultListableBeanFactory();//manage bean factory
        ClassPathResource resource = new ClassPathResource(
                "applicationContext.xml");//resource
        XmlBeanDefinitionReader xmlReader=new XmlBeanDefinitionReader((BeanDefinitionRegistry)beanFactory); //register
        
        public Test4DebugSpringIOC() {
            // TODO load and registered BeanDefinition
            xmlReader.loadBeanDefinitions(resource);
        }
        public static void main(String[] args) {
            Test4DebugSpringIOC test4DebugSpring= new Test4DebugSpringIOC();
            Test4DebugSpringBean test4DebugSpringBean = (Test4DebugSpringBean) test4DebugSpring.beanFactory
                    .getBean("testAlias");
            test4DebugSpringBean.SayHolle();
        }
    }
    复制代码

     1,找到bean的定义文件(Resource)

          如此处classPathResource,用于找到文件位置

     2,把定义文件解析成BeanDefinition对象并进行注册,在XmlBeanDefinitionReader中

                int validationMode = getValidationModeForResource(resource);//Validation xml file  . XmlBeanDefinitionReader doLoadBeanDefinitions
                Document doc = this.documentLoader.loadDocument(
                        inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());//parse to doc . through documentLoader(DefaultDocumentLoader)
                return registerBeanDefinitions(doc, resource);

    一个普通bean的解析step 

     i 调用DefaultDocumentLoader把XML解析成DOC并进行XSD,DTD等格式验证.

     DefaultDocumentLoader调用了SAX的DocumentBuilderFactory.newInstance(),把XML文件解析成一个org.w3c.dom.Document对象(标准的DOM解析方式),当然也设置XML验证的validationMode,namespace

    复制代码
        /**
         * Load the {@link Document} at the supplied {@link InputSource} using the standard JAXP-configured
         * XML parser.
         */
        public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
                ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {
    
            DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
            if (logger.isDebugEnabled()) {
                logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]");
            }
            DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
            return builder.parse(inputSource);
        }
    复制代码

    ii DefaultBeanDefinitionDocumentReader读取document中的所有Element. 

    registerBeanDefinitions(doc, resource)中调用BeanDefinitionDocumentReader的registerBeanDefinitions方法获根节点

    public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
    		this.readerContext = readerContext;
    
    		logger.debug("Loading bean definitions");
    		Element root = doc.getDocumentElement();
    
    		doRegisterBeanDefinitions(root);
    	}
    

    得到XML的根节点,调用doRegisterBeanDefinitions

    复制代码
        /**
         * Register each bean definition within the given root {@code <beans/>} element.
         * @throws IllegalStateException if {@code <beans profile="..."} attribute is present
         * and Environment property has not been set
         * @see #setEnvironment
         */
        protected void doRegisterBeanDefinitions(Element root) {
    ..//profile
    
            // any nested <beans> elements will cause recursion in this method. In
            // order to propagate and preserve <beans> default-* attributes correctly,
            // keep track of the current (parent) delegate, which may be null. Create
            // the new (child) delegate with a reference to the parent for fallback purposes,
            // then ultimately reset this.delegate back to its original (parent) reference.
            // this behavior emulates a stack of delegates without actually necessitating one.
            BeanDefinitionParserDelegate parent = this.delegate;
            this.delegate = createHelper(readerContext, root, parent);
    
            preProcessXml(root);
            parseBeanDefinitions(root, this.delegate);
            postProcessXml(root);
    
            this.delegate = parent;
        }
    复制代码

    然后从获得根结点的所有子节点,进行循环

    复制代码
        /**
         * Parse the elements at the root level in the document:
         * "import", "alias", "bean".
         * @param root the DOM root element of the document
         */
        protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
            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)) {
                            parseDefaultElement(ele, delegate);//parse defalut element
                        }
                        else {
                            delegate.parseCustomElement(ele);
                        }
                    }
                }
            }
            else {
                delegate.parseCustomElement(root);
            }
        }
    复制代码

     此处isDefaultNamespace方法是获取namespace为http://www.springframework.org/schema/beans的node,目前对应schema定义的包括"bean" "alis" "beans" "import" ,处理方法为parseDefaultElement(ele, delegate),如果发现是bean标签则调用processBeanDefinition方法

    复制代码
        /**
         * Process the given bean element, parsing the bean definition
         * and registering it with the registry.
         */
        protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
            BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); //parse to object of BeanDefinitionHolder
            if (bdHolder != null) {//if it is not exit. parse it from xml
                bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
                try {
                    // Register the final decorated instance.
                    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));
            }
        }
    复制代码

    iii 调用BeanDefinitionParserDelegate对象完成doc中Element->BeanDefinitionHolder的转换

    复制代码
        /**
         * Parses the supplied <code>&lt;bean&gt;</code> element. May return <code>null</code>
         * if there were errors during parse. Errors are reported to the
         * {@link org.springframework.beans.factory.parsing.ProblemReporter}.
         */
        public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
            String id = ele.getAttribute(ID_ATTRIBUTE);
            String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
    ... ... //vacation
            AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
    ....
    
    return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
            }
    复制代码

    先获得别名,这里叫nameAttr先转成数组,然后通过BeanDefinitionHolder把它和beanName,beandefine绑定在一起

    复制代码
    /**
         * Parse the bean definition itself, without regard to name or aliases. May return
         * <code>null</code> if problems occurred during the parsing of the bean definition.
         */
        public AbstractBeanDefinition parseBeanDefinitionElement(
                Element ele, String beanName, BeanDefinition containingBean) {
    
            this.parseState.push(new BeanEntry(beanName));
    
            String className = null;
            if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
                className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
            }
    
            try {
                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));
    
                parseMetaElements(ele, bd);
                parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
                parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
    
                parseConstructorArgElements(ele, bd);
                parsePropertyElements(ele, bd);
                parseQualifierElements(ele, bd);
    
                bd.setResource(this.readerContext.getResource());
                bd.setSource(extractSource(ele));
    
                return bd;
            }
    复制代码

    全部当成属性设置到了AbstractBeanDefinition 的对象中,具体可以看AbstractBeanDefinition 类

    最后返回BeanDefinitionHolder;BeanDefinitionHolder是由beanname+aliasArray+beandefinition组成的一个对象

    IV 然后回到ii的最后调用BeanDefinitionReaderUtils.registerBeanDefinition注册beandefine对象,并调BeanDefinitionRegistry接口进行注册,如DefaultListableBeanFactory

    完成转换后,BeanDefinitionReaderUtils.registerBeanDefinition 调用到 BeanDefinitionRegistry接口实现类的registerBeanDefinition方法把对象放入bean的工厂容器中

    复制代码
         * Register the given bean definition with the given bean factory.
         * @param definitionHolder the bean definition including name and aliases
         * @param registry the bean factory to register with
         * @throws BeanDefinitionStoreException if registration failed
         */
        public static void registerBeanDefinition(
                BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
                throws BeanDefinitionStoreException {
    
            // Register bean definition under primary name.
            String beanName = definitionHolder.getBeanName();
            registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
    
            // Register aliases for bean name, if any.
            String[] aliases = definitionHolder.getAliases();
            if (aliases != null) {
                for (String aliase : aliases) {
                    registry.registerAlias(beanName, aliase);
                }
            }
        }
    复制代码

     在DefaultListableBeanFactory的实现也很简单了,直接用map添加下就OK了

    复制代码
        public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
                throws BeanDefinitionStoreException {
    ....//Validation
    
                this.beanDefinitionMap.put(beanName, beanDefinition);//add it to beanDefinitionMap
            }
    
            resetBeanDefinition(beanName); //reset all exist
        }
    复制代码

     3,查找,通过getbean获得bean,用ConfigurableListableBeanFactory,如DefaultListableBeanFactory

    这部分功能主要在abstractbeanfactory中完成,如果是singleton(即spring的default)

    i   transformedBeanName(name) ,得到SimpleAliasRegistry 的 map 属性 aliasMap,转换为beanname(别名功能)

    ii  Object sharedInstance = getSingleton(beanName); 尝试从DefaultSingletonBeanRegistry的MAP singletonObjects中拿出bean (singleton功能)

    iii  bean = getObjectForBeanInstance(sharedInstance, name, beanName, null) 处理factorybean部分,附 Spring FactoryBean源码浅析

    iv final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 从bean注册的信息中找到bean 对应的 BeanDefinition

    v return createBean(beanName, mbd, args); 创建新的bean,通过BeanDefinition的描述信息来,并填充到DefaultSingletonBeanRegistry的singletonObjects中

    beanfactory的主要代码,加上了些注释

    复制代码
        /**
         * Return an instance, which may be shared or independent, of the specified bean.
         * @param name the name of the bean to retrieve
         * @param requiredType the required type of the bean to retrieve
         * @param args arguments to use if creating a prototype using explicit arguments to a
         * static factory method. It is invalid to use a non-null args value in any other case.
         * @param typeCheckOnly whether the instance is obtained for a type check,
         * not for actual use
         * @return an instance of the bean
         * @throws BeansException if the bean could not be created
         */
        @SuppressWarnings("unchecked")
        protected <T> T doGetBean(
                final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
                throws BeansException {
            final String beanName = transformedBeanName(name); //get true name from attribute aliasMap of SimpleAliasRegistry
            Object bean;
            // Eagerly check singleton cache for manually registered singletons.
            Object sharedInstance = getSingleton(beanName); //get instance object from the attribute singletonObjects of DefaultSingletonBeanRegistry
            if (sharedInstance != null && args == null) {
                if (logger.isDebugEnabled()) {
                    if (isSingletonCurrentlyInCreation(beanName)) {
                        logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                                "' that is not fully initialized yet - a consequence of a circular reference");
                    }
                    else {
                        logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
                    }
                }
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); // it is for that class witch is implement interface factorybean
            }
    
            else {
                // Fail if we're already creating this bean instance:
                // We're assumably within a circular reference.
                if (isPrototypeCurrentlyInCreation(beanName)) {
                    throw new BeanCurrentlyInCreationException(beanName);
                }
    
                // Check if bean definition exists in this factory.
                BeanFactory parentBeanFactory = getParentBeanFactory();
                if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                    // Not found -> check parent.
                    String nameToLookup = originalBeanName(name);
                    if (args != null) {
                        // Delegation to parent with explicit args.
                        return (T) parentBeanFactory.getBean(nameToLookup, args);
                    }
                    else {
                        // No args -> delegate to standard getBean method.
                        return parentBeanFactory.getBean(nameToLookup, requiredType);
                    }
                }
    
                if (!typeCheckOnly) {
                    markBeanAsCreated(beanName);
                }
    
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);//get BeanDefinition from registered information
                checkMergedBeanDefinition(mbd, beanName, args);
    
                // Guarantee initialization of beans that the current bean depends on.
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dependsOnBean : dependsOn) {
                        getBean(dependsOnBean);
                        registerDependentBean(dependsOnBean, beanName);
                    }
                }
    
                // Create bean instance.
                if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                        //create new instance and put in attribute map singletonObjects of DefaultSingletonBeanRegistry
                        public Object getObject() throws BeansException {
                            try {
                                return createBean(beanName, mbd, args);
                            }
                            catch (BeansException ex) {
                                // Explicitly remove instance from singleton cache: It might have been put there
                                // eagerly by the creation process, to allow for circular reference resolution.
                                // Also remove any beans that received a temporary reference to the bean.
                                destroySingleton(beanName);
                                throw ex;
                            }
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }
    
                else if (mbd.isPrototype()) {
                    // It's a prototype -> create a new instance.
                    Object prototypeInstance = null;
                    try {
                        beforePrototypeCreation(beanName);
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {
                        afterPrototypeCreation(beanName);
                    }
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }
    
                else {
                    String scopeName = mbd.getScope();
                    final Scope scope = this.scopes.get(scopeName);
                    if (scope == null) {
                        throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
                    }
                    try {
                        Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
                            public Object getObject() throws BeansException {
                                beforePrototypeCreation(beanName);
                                try {
                                    return createBean(beanName, mbd, args);
                                }
                                finally {
                                    afterPrototypeCreation(beanName);
                                }
                            }
                        });
                        bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    }
                    catch (IllegalStateException ex) {
                        throw new BeanCreationException(beanName,
                                "Scope '" + scopeName + "' is not active for the current thread; " +
                                "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                                ex);
                    }
                }
            }
    
            // Check if required type matches the type of the actual bean instance.
            if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
                try {
                    return getTypeConverter().convertIfNecessary(bean, requiredType);
                }
                catch (TypeMismatchException ex) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Failed to convert bean '" + name + "' to required type [" +
                                ClassUtils.getQualifiedName(requiredType) + "]", ex);
                    }
                    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                }
            }
            return (T) bean;
        }
    复制代码

    附 bean中的主要结构

    主要类,下列类从上往下继承

    SimpleAliasRegistry 用于维护一个 aliasMap,维护别名功能

    DefaultSingletonBeanRegistry map 维护 singletonObjects,维护工厂单例,一个工厂一个单例,非N个工厂一个单例

    FactoryBeanRegistrySupport

    AbstractBeanFactory ,factorybean的主要实现类,其doGetBean,getBean是主要获得bean的入口 ,维护一个mergedBeanDefinitions

    AbstractAutowireCapableBeanFactory,configureableBeanFactory的主要实现类,  createBean根据beandefine的信息创建相应的值

    DefaultListableBeanFactory ConfigurableListableBeanFactory和BeanDefinitionRegistry接口的主要实现类,维护beanDefiniti信息

    主要接口关系如下

    image

    Parse XML主要用到的几个相关类

    * @see DocumentLoader
    * @see DefaultDocumentLoader

    TODO 对SAX几个工厂属性进行设置,schema等,调用SAX对XML转换成了DOC对象

    * @see BeanDefinitionDocumentReader  
    * @see DefaultBeanDefinitionDocumentReader

    提供registerBeanDefinitions,和setEnvironment方法,用于DOC到beandefine的注册功能,遍历了doc的所有node,调用 BeanDefinitionParserDelegate解析node,并调用BeanDefinitionReaderUtils对解析的beandefine到beandefine注册类的注册

    * @BeanDefinitionParserDelegate

    主要解析类,各种属性,对beandefine对象属性的设置都是在此类完成

    bean中ConfigurableListableBeanFactory接口继承了bean中的基本接口,DefaultListableBeanFactory是其唯一实现类,也是预留接口供扩展

    接口因为可以多继承,所以用来表示系统的结构最合适不过,而JAVA中类单继承的,一般只是用来实现设计,侧重实现功能,因为类层次肯定是一条线。

     
     
  • 相关阅读:
    Java——HTTPServletRequest的使用
    JavaWeb——HttpServletResponse的使用,文件下载
    JavaWeb——Servlet简介
    JavaWeb——TomCat服务器
    HTTP与HTTPS
    Java——DBCP连接池
    Java——JDBC连接MySQL
    Java——线程锁,死锁,等待唤醒机制
    LeetCode118. 杨辉三角
    LeetCode66. 加一
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2874361.html
Copyright © 2011-2022 走看看