Spring源码(一)

Spring源码阅读(一)

1.IOC工厂核心部分

1.工厂如何解析xml

1.怎么读取配置文件,获得IO资源

在我们的Spring框架中,我们有封装的资源读取接口Resource,而在这个接口中的实现类例如:

ClassPathResource

ServletContextResource

我们只需要获取一个核心内容即InputStream,我们的jvm虚拟机只需要对不同资源的输入流的内容来进行读取即可

例如我们的一个配置文件中定义了applicaionConText.xml

<bean id ="user" class = "xxx.xxx.User">bean>
<bean id ="account" class = "xxx.xxx.Account">bean>

自然我们的Resource接口对应的实现类ClassPathResource进行读取并获取InputStream输入流,最终呢这些配置文件的相关信息在我们的jvm中都是以对象的形式体现的

那么问题来了?这些配置的相关信息用哪一个对象来存储

其实就是我们的BeanDefinition接口的实现对象

而最常用的就是GenricBeanDefinition

那么我们梳理一下整个流程,我们用Resourse的实现类来读取我们的xml配置文件并且获取到了输入流,并通过将输入流的内容封装成我们的BeanDefinition对象,那么这一个过程是谁做的呢?

这里就引出了我们的XmlBeanDefinitionReader就是获取输入流之后,将配置文件的信息封装成BeanDefinition,而这个类对象是在我们的XmlBeanFactory中注入的

在我们的XmlBeanFactory的源码中

public class XMlBeanFactory extends DefaultListableBeanFactory{
    //在我们的XmlBeanFactory中就会有这样的一个reader
    private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this)
    //...
}

接下来我们使用我们的XmlBeanDefinitionReader 和 我们的DefaultListableBeanFactory来模拟我们的XmlBeanFactory来实现读取替换

@Test
public void test(){
    BeanFactory factory = new XmlBeanFactory(new ClassPathResource("applicaion.xml"));
    Product product = (Product) factory.getBean("u");
    
    //用XmlBeanDefinitionReader和DefaultListableBeanFactory替换
    BeanFactory beanFactory = new DefaultListableBeanFactory();
    Resource resource = new ClasspathResource("applicaion.xml");
    XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
    xmlBeanDefinitionReader.loadBeanDefinitions(resource);
    Object product = beanFactory.get("product");
} 
2 .读取配置文件后,如何在Spring中以对象的形式进行封装

我们知道了这个过程是谁来做的,那么自然我们接下来就想研究一下怎么做的即

Spring底层如何做到使用XmlBeanDeifintionReader读取我们XML封装成BeanDefinition

我们再来看我们new这个XmlBeanFactory工厂的构造方法

    /**
     * 根据Resource实例化XmlBeanFactory
     * @param resource
     * @throws BeansException
     */
    public XmlBeanFactory(Resource resource) throws BeansException {
        this(resource, null);
    }

    /**
     * 根据Resource和BeanFactory实例化XmlBeanFactory
     * @param resource
     * @param parentBeanFactory
     * @throws BeansException
     */
    public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
        super(parentBeanFactory);
        this.reader.loadBeanDefinitions(resource);
    }

通过上面方法我们发现我们的构造器还有一个参数即我们的父容器

Spring允许一个工程中有多个Spring工厂同时出现,情况非常少见

SpringMVC中的父子容器

​ DispatcherServlet–childFactory

​ ContextLoaderListener–rootFactory

我们开发中这种情况非常少见所以在这里我们可以将其忽略掉

接下来我们就主要看我们reader的loadBeanDefinitions这个方法了

进来发现包了一层参数为EncodeResource的重载方法也就是new了一个EncodeResource里面放我们原的Resource

//下面就是Encode重载方法
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
      return this.loadBeanDefinitions(new EncodedResource(resource));
}
//这个才是主要走的方法
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
    	//第一段打日志
        Assert.notNull(encodedResource, "EncodedResource must not be null");
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("Loading XML bean definitions from " + encodedResource);
        }
		//考虑在本配置文件之前有多个配置文件所以用set
        Set<EncodedResource> currentResources = (Set)this.resourcesCurrentlyBeingLoaded.get();
        if (!currentResources.add(encodedResource)) {
            throw new BeanDefinitionStoreException("Detected cyclic loading of " + encodedResource + " - check your import definitions!");
        } else {
            //之前未被加载过
            int var6;
            try {
                //这是最为核心的部分
                //下面就是获得我们配置文件的输入流
                InputStream inputStream = encodedResource.getResource().getInputStream();
                Throwable var4 = null;

                try {
                    //这个InputSource是专门用来给xml解析的一个工具类
                    //他的包是package org.xml.sax;
                    //是我们的java提供的xml解析的工具类
                    InputSource inputSource = new InputSource(inputStream);
                    if (encodedResource.getEncoding() != null) {
                        inputSource.setEncoding(encodedResource.getEncoding());
                    }
                    //给了配置文件以及解析我们xml的工具所以下面这个方法才是核心!
                    //我们继续断点进去
                    var6 = this.doLoadBeanDefinitions(inputSource, encodedResource.getResource());
                } catch (Throwable var24) {
                    var4 = var24;
                    throw var24;
                } finally {
                    if (inputStream != null) {
                        if (var4 != null) {
                            try {
                                inputStream.close();
                            } catch (Throwable var23) {
                                var4.addSuppressed(var23);
                            }
                        } else {
                            inputStream.close();
                        }
                    }
                }
            } catch (IOException var26) {
                throw new BeanDefinitionStoreException("IOException parsing XML document from " + encodedResource.getResource(), var26);
            } finally {
                currentResources.remove(encodedResource);
                if (currentResources.isEmpty()) {
                    this.resourcesCurrentlyBeingLoaded.remove();
                }

            }

            return var6;
        }
    }
/******************************************************************************************************************************/
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
        try {
            //实质性的代码也就只有这两行
            //我们这个Document对象是干嘛的呢
            //这个int就是封装了几个BeanDefinition了
            Document doc = this.doLoadDocument(inputSource, resource);
            //那我们就要进入我们的registerBeanDefinitions方法了
            int count = this.registerBeanDefinitions(doc, resource);
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Loaded " + count + " bean definitions from " + resource);
            }

            return count;
        } catch (BeanDefinitionStoreException var5) {
            throw var5;
        } catch (SAXParseException var6) {
            throw new XmlBeanDefinitionStoreException(resource.getDescription(), "Line " + var6.getLineNumber() + " in XML document from " + resource + " is invalid", var6);
        } catch (SAXException var7) {
            throw new XmlBeanDefinitionStoreException(resource.getDescription(), "XML document from " + resource + " is invalid", var7);
        } catch (ParserConfigurationException var8) {
            throw new BeanDefinitionStoreException(resource.getDescription(), "Parser configuration exception parsing XML from " + resource, var8);
        } catch (IOException var9) {
            throw new BeanDefinitionStoreException(resource.getDescription(), "IOException parsing XML document from " + resource, var9);
        } catch (Throwable var10) {
            throw new BeanDefinitionStoreException(resource.getDescription(), "Unexpected exception parsing XML document from " + resource, var10);
        }
    }

/******************************************************************************************************************************/
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
        BeanDefinitionDocumentReader documentReader = this.createBeanDefinitionDocumentReader();
        int countBefore = this.getRegistry().getBeanDefinitionCount();
    //这个就很易懂了获得DocumentReader然后又获取之前已经注册的BeanDefinition数量,然后注册
    //核心又是registerBeanDefinitions方法
    //好好好你这么玩是吧
        documentReader.registerBeanDefinitions(doc, this.createReaderContext(resource));
    //注册完返回差值不就正好是注册了几个BeanDefinition了吗
        return this.getRegistry().getBeanDefinitionCount() - countBefore;
    }
/******************************************************************************************************************************/
//又重载 发现了前缀是do的才是干活了的
 public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
        this.readerContext = readerContext;
        this.doRegisterBeanDefinitions(doc.getDocumentElement());
    }
//
protected void doRegisterBeanDefinitions(Element root) {
        BeanDefinitionParserDelegate parent = this.delegate;
        this.delegate = this.createDelegate(this.getReaderContext(), root, parent);
        if (this.delegate.isDefaultNamespace(root)) {
            //这个是解析根标签里面的profile标签(这个profile是个啥)
            //其实就是我们xml里面可以定义不同环境下的bean对象,可以通过profile切换来涉及到我们对象的改变
            //
            //
            //
            // 
            //设置了profile之后我们是为了相应的环境上的区分
            //配置上了我们在哪区分呢(springmvc中)
            //在我们的springmvc中有一个配置
            //
            //	Spring.profiles.active
            //	dev
            //	这个dev就是我们profile的值
            //
            String profileSpec = root.getAttribute("profile");
            if (StringUtils.hasText(profileSpec)) {
                String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, ",; ");
                if (!this.getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                    if (this.logger.isDebugEnabled()) {
                        this.logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec + "] not matching: " + this.getReaderContext().getResource());
                    }

                    return;
                }
            }
        }
    	//上面这块的作用其实就是对profile值的读取了
        this.preProcessXml(root);
    	//下面这一行才是最为重要的
        this.parseBeanDefinitions(root, this.delegate);
        this.postProcessXml(root);
        this.delegate = parent;
    }
/******************************************************************************************************************************/

 protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
        if (delegate.isDefaultNamespace(root)) {
            //这里就是获得我们root标签即beans标签的子节点了
            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)) {
                        //这个是解析基本标签的
                        this.parseDefaultElement(ele, delegate);
                    } else {
                        //这个是解析自定义标签的
                        delegate.parseCustomElement(ele);
                    }
                    //那么什么是基本标签了?
                    //
                    //	
                    //	
                    //
                    //那么什么是自定义标签? 新的命名空间标签
                    //
                    //
                    //
                    //
                    //有自定义头的就是自定义标签
                    //自定义标签会自动注册一些类,但是我们并不知道注入了哪些
                }
            }
        } else {
            delegate.parseCustomElement(root);
        }

    }
/******************************************************************************************************************************/
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
        if (delegate.nodeNameEquals(ele, "import")) {
            this.importBeanDefinitionResource(ele);
        } else if (delegate.nodeNameEquals(ele, "alias")) {
            this.processAliasRegistration(ele);
        } else if (delegate.nodeNameEquals(ele, "bean")) {
            this.processBeanDefinition(ele, delegate);
        } else if (delegate.nodeNameEquals(ele, "beans")) {
            this.doRegisterBeanDefinitions(ele);
        }

    }
//这个就很明了了,对应import alias bean 以及(针对有profiles的)内嵌的beans标签
//import标签就是引入其他资源的(例如)
//
//alias标签:是别名的意思
//
//我 想为user起别名
//
//等价于

//这样我们的user就是有别名u了
//Bean标签就是我们最需要看的了
/******************************************************************************************************************************/
//BeanDefinitionParserDelegate delegate 这玩意就是个委托对象,其实也就是个解析器BeanDefinitionParser
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    //把bean标签的内容解析封装成BeanDefinitionHolder
    //这个Holder就是对BeanDefinition做了包装,其实也就是BeanDefinition
    //里面有BeanDefintion beanName aliases(就是包装了名字和别名)
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        if (bdHolder != null) {
            //如果bean标签里面又嵌套了 自定义的标签
            //我们用这个方法进行再次解析(一般不用)
            bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
            try {
                //这一块就是注册我们的BeanDefinition了
                //要把整个spring工厂中所涉及的BeanDefinition给存储起来
                //我们存储在什么结构呢?(当然是Map)
                //1.存储多个BD
                //2.最好查询 k-v
                //key id
                //value BDH
                //存的就是BeanDefinitionHolder
                BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
            } catch (BeanDefinitionStoreException var5) {
                this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5);
            }
            //send registration event
            //发送一个事件表明已经注册完成了,那么就是我们可以监听整个事件来做一些后续操作
            //但是这个spring也没想好做什么,你自己可以来解决(springboot做了)
            this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
        }

    }
//到这里我们就会发现两个关键点,一个是如何解析转化为BeanDefinitionHolder,第二个是如何注册即
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
/******************************************************************************************************************************/
//下面这个重载就不看了(就是设置了个null值)
 @Nullable
    public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
        return this.parseBeanDefinitionElement(ele, (BeanDefinition)null);
    }

    @Nullable
    public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
        //下面这不就是获取id和name属性吗
        String id = ele.getAttribute("id");
        String nameAttr = ele.getAttribute("name");
        //这就是别名列表啊
        List<String> aliases = new ArrayList();
        //只要有name属性
        if (StringUtils.hasLength(nameAttr)) {
            //根据分隔符,和;拆分出成数组
            String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, ",; ");
            //添加别名数组
            aliases.addAll(Arrays.asList(nameArr));
        }
        //id就是beanName
        String beanName = id;
        //如果不存在id但是存在别名
        if (!StringUtils.hasText(id) && !aliases.isEmpty()) {
            //把第一个别名作为beanName了(移除别名列表)
            beanName = (String)aliases.remove(0);
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases");
            }
        }
        //上面就是处理beanName和alias
        if (containingBean == null) {
            //重载给了null
            //确认这个名字是否在注册表唯一
            this.checkNameUniqueness(beanName, aliases, ele);
        }
        //开始真正创建BeanDefinition了
        //parseBeanDefinitionElement方法处理了其他属性例如class,scope,abstract,autowire init-method lazy-int等
        //这里还要走进去
        AbstractBeanDefinition beanDefinition = this.parseBeanDefinitionElement(ele, beanName, containingBean);
        //解析完成
        if (beanDefinition != null) {
            if (!StringUtils.hasText(beanName)) {
                //这里就是即没有id又没有alias,那么会使用一个默认的算法给我们生成一个(BeanDefinitionReaderUtils.generateBeanName)
                //下面try里面都是干这事 
                try {
                    if (containingBean != null) {
                        beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true);
                    } else {
                        beanName = this.readerContext.generateBeanName(beanDefinition);
                        String beanClassName = beanDefinition.getBeanClassName();
                        if (beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
                            aliases.add(beanClassName);
                        }
                    }

                    if (this.logger.isTraceEnabled()) {
                        this.logger.trace("Neither XML 'id' nor 'name' specified - using generated bean name [" + beanName + "]");
                    }
                } catch (Exception var9) {
                    this.error(var9.getMessage(), ele);
                    return null;
                }
            }

            String[] aliasesArray = StringUtils.toStringArray(aliases);
            return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
        } else {
            return null;
        }
    }
//进入我们的parseBeanDefinitionElement的内容
//在这个里面就把bean标签下面的所有嵌套的以及bean标签的属性全部解析完成了
 @Nullable
    public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, @Nullable BeanDefinition containingBean) {
        
        this.parseState.push(new BeanEntry(beanName));
        String className = null;
        //解析class标签
        if (ele.hasAttribute("class")) {
            className = ele.getAttribute("class").trim();
        }
        //解析parent标签
        String parent = null;
        if (ele.hasAttribute("parent")) {
            parent = ele.getAttribute("parent");
        }

        try {
            //创建BeanDefinition
            AbstractBeanDefinition bd = this.createBeanDefinition(className, parent);
            //下面这个方法将bean标签的属性内容给解析了
            this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
            bd.setDescription(DomUtils.getChildElementValueByTagName(ele, "description"));
            this.parseMetaElements(ele, bd);
            //开始解析bean内嵌的各种标签的内容 例如property,constructor-method lookup-method replaced-method
            this.parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
            this.parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
            this.parseConstructorArgElements(ele, bd);
            //这个property标签的解析可以一看
            this.parsePropertyElements(ele, bd);
            this.parseQualifierElements(ele, bd);
            bd.setResource(this.readerContext.getResource());
            bd.setSource(this.extractSource(ele));
            AbstractBeanDefinition var7 = bd;
            return var7;
        } catch (ClassNotFoundException var13) {
            this.error("Bean class [" + className + "] not found", ele, var13);
        } catch (NoClassDefFoundError var14) {
            this.error("Class that bean class [" + className + "] depends on not found", ele, var14);
        } catch (Throwable var15) {
            this.error("Unexpected failure during bean definition parsing", ele, var15);
        } finally {
            this.parseState.pop();
        }

        return null;
    }

进入我们的 this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
//解析了例如scope,abstrct,lazy-init,autowire,depends on等属性
  public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName, @Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {
        if (ele.hasAttribute("singleton")) {
            this.error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
        } else if (ele.hasAttribute("scope")) {
            bd.setScope(ele.getAttribute("scope"));
        } else if (containingBean != null) {
            bd.setScope(containingBean.getScope());
        }

        if (ele.hasAttribute("abstract")) {
            bd.setAbstract("true".equals(ele.getAttribute("abstract")));
        }

        String lazyInit = ele.getAttribute("lazy-init");
        if (this.isDefaultValue(lazyInit)) {
            lazyInit = this.defaults.getLazyInit();
        }

        bd.setLazyInit("true".equals(lazyInit));
        String autowire = ele.getAttribute("autowire");
        bd.setAutowireMode(this.getAutowireMode(autowire));
        String autowireCandidate;
        if (ele.hasAttribute("depends-on")) {
            autowireCandidate = ele.getAttribute("depends-on");
            bd.setDependsOn(StringUtils.tokenizeToStringArray(autowireCandidate, ",; "));
        }

        autowireCandidate = ele.getAttribute("autowire-candidate");
        String destroyMethodName;
        if (this.isDefaultValue(autowireCandidate)) {
            destroyMethodName = this.defaults.getAutowireCandidates();
            if (destroyMethodName != null) {
                String[] patterns = StringUtils.commaDelimitedListToStringArray(destroyMethodName);
                bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
            }
        } else {
            bd.setAutowireCandidate("true".equals(autowireCandidate));
        }

        if (ele.hasAttribute("primary")) {
            bd.setPrimary("true".equals(ele.getAttribute("primary")));
        }

        if (ele.hasAttribute("init-method")) {
            destroyMethodName = ele.getAttribute("init-method");
            bd.setInitMethodName(destroyMethodName);
        } else if (this.defaults.getInitMethod() != null) {
            bd.setInitMethodName(this.defaults.getInitMethod());
            bd.setEnforceInitMethod(false);
        }

        if (ele.hasAttribute("destroy-method")) {
            destroyMethodName = ele.getAttribute("destroy-method");
            bd.setDestroyMethodName(destroyMethodName);
        } else if (this.defaults.getDestroyMethod() != null) {
            bd.setDestroyMethodName(this.defaults.getDestroyMethod());
            bd.setEnforceDestroyMethod(false);
        }

        if (ele.hasAttribute("factory-method")) {
            bd.setFactoryMethodName(ele.getAttribute("factory-method"));
        }

        if (ele.hasAttribute("factory-bean")) {
            bd.setFactoryBeanName(ele.getAttribute("factory-bean"));
        }

        return bd;
    }

//this.parsePropertyElements(ele, bd);
 public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
        NodeList nl = beanEle.getChildNodes();//得到子标签
        for(int i = 0; i < nl.getLength(); ++i) {
            Node node = nl.item(i);
            //找到并且解析该条property标签
            if (this.isCandidateElement(node) && this.nodeNameEquals(node, "property")) {
                this.parsePropertyElement((Element)node, bd);
            }
        }

    }

//parsePropertyElement

public void parsePropertyElement(Element ele, BeanDefinition bd) {
        String propertyName = ele.getAttribute("name");
        if (!StringUtils.hasLength(propertyName)) {
            this.error("Tag 'property' must have a 'name' attribute", ele);
        } else {
            this.parseState.push(new PropertyEntry(propertyName));

            try {
                if (bd.getPropertyValues().contains(propertyName)) {
                    this.error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
                    return;
                }

                Object val = this.parsePropertyValue(ele, bd, propertyName);
                PropertyValue pv = new PropertyValue(propertyName, val);
                this.parseMetaElements(ele, pv);
                pv.setSource(this.extractSource(ele));
                //所有的property标签全部封装到了BeanDefinition里面的属性MutablePropertyValues
                bd.getPropertyValues().addPropertyValue(pv);
            } finally {
                this.parseState.pop();
            }
        }
    }
/******************************************************************************************************************************/
//这些好了我们看注册 (到了我们的BeanDefinition的存储了)

我们这的Document和我们的Spring没有关系!!

它是我们xml解析的对象

inputSource --》xml --》Document --》 XML解析相关操作

Spring说它用的也不方便啊,所以Spring将它拿去转换

Document–>BeanDefinition

所以一共就干了两件事

第一件:通过InputSource工具解析XML获取到Document

第二件:把Document转化成BeanDefinition

总结:工厂解析两种标签,分别是自定义标签和默认标签并且将其封装为BeanDefinition

注:到了这里就是注册了,但是注册绝不等于调用

只有当创建对象的时候才会通过反射来将我们BeanDefinition的信息创建为对象

public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
    //这里拿到了我们的Bean的名字,用k-v值来进行注册
        String beanName = definitionHolder.getBeanName();
        String alias = var4[var6];
        //用注册器来进行注册
    	//那么我们的注册器应该用哪一个呢,其实就目前我们讨论的xmlBeanFactory是DefualtListableBeanFactory的
        registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
        String[] aliases = definitionHolder.getAliases();
        if (aliases != null) {
            String[] var4 = aliases;
            int var5 = aliases.length;

            for(int var6 = 0; var6 < var5; ++var6) {
                registry.registerAlias(beanName, alias);
            }
        }
    }
/******************************************************************************************************************************/
//我们来进入DefualtListableBeanFactory的regiterBeanDefinition方法里
 public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
     	//下面都是校验
        Assert.hasText(beanName, "Bean name must not be empty");
        Assert.notNull(beanDefinition, "BeanDefinition must not be null");
        if (beanDefinition instanceof AbstractBeanDefinition) {
            try {
                ((AbstractBeanDefinition)beanDefinition).validate();
            } catch (BeanDefinitionValidationException var8) {
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var8);
            }
        }
     //我先拿一下你的这个beanName的key来看看是否已经有这个beanid的bean了
        BeanDefinition existingDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
        if (existingDefinition != null) {
            //下面就是对已经存在的该beanid的处理了我们可以选择性跳过
            if (!this.isAllowBeanDefinitionOverriding()) {
                throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
            }

            if (existingDefinition.getRole() < beanDefinition.getRole()) {
                if (this.logger.isInfoEnabled()) {
                    this.logger.info("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
                }
            } else if (!beanDefinition.equals(existingDefinition)) {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
                }
            } else if (this.logger.isTraceEnabled()) {
                this.logger.trace("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
            }

            this.beanDefinitionMap.put(beanName, beanDefinition);
        } else {
            //无法再修改启动时收集元素
            if (this.hasBeanCreationStarted()) {
      
                synchronized(this.beanDefinitionMap) {
                    this.beanDefinitionMap.put(beanName, beanDefinition);
                    List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);
                    updatedDefinitions.addAll(this.beanDefinitionNames);
                    updatedDefinitions.add(beanName);
                    this.beanDefinitionNames = updatedDefinitions;
                    this.removeManualSingletonName(beanName);
                }
            } else {
                //仍处于启动注册的阶段
                //下面是不是就存进去了
                //一个是beanDefinitionMap,一个是beanDefinitionNames
                //一个显然是map,一个显然是list
                //这里就是我们这个方法中最关键的部分
                this.beanDefinitionMap.put(beanName, beanDefinition);
                this.beanDefinitionNames.add(beanName);  
                this.removeManualSingletonName(beanName);
            }

            this.frozenBeanDefinitionNames = null;
        }

        if (existingDefinition == null && !this.containsSingleton(beanName)) {
            if (this.isConfigurationFrozen()) {
                this.clearByTypeCache();
            }
        } else {
            this.resetBeanDefinition(beanName);
        }

    }


//自然在我们注册完之后就返回上一层的
 this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
发送BeanDefinition注册完成的是事件
    目的:扩展点 ---> 预留埋点
    若想要实现回调
    就实现ReaderEventListener并且注册到我们的spring工厂中即可
    
最终我们知道了我们的BeanDefinition存在了我们工厂的
    beanDefinitionMap
    而beanName存在了我们的beanDefinitionNames里面

我们上面好像只讨论了default即默认标签的解析

接下面我们仍然需要解析我们的自定义标签了

例如 -->类

我们发现当我们引入了这个标签之后

我们的xml中会多出xsi:schemaLocation引入的一些东西

https://www.springframework.org/schema/mvc

https://www.springframework.org/schema/mvc/spring-mvc.xsd

他们就是我们spring-webmvc包中的resources里面的META-INF里面的spring.schemas里面的东西

https://www.springframework.org/schema/mvc/spring-mvc.xsd=org/springframework/web/servlet/config/spring-mvc.xsd

这样我们才能使用mvc这个自定义标签头

而Meta-INF里面的spring.handlers也非常重要

它代表我们自定义的标签会被哪一个handler解析

mvc自定义标签就是会

MvcNameSpaceHandler这个Handler解析

public class MvcNamespaceHandler extends NamespaceHandlerSupport {
    public MvcNamespaceHandler() {
    }

    public void init() {
        this.registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
        this.registerBeanDefinitionParser("default-servlet-handler", new DefaultServletHandlerBeanDefinitionParser());
        this.registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());
        this.registerBeanDefinitionParser("resources", new ResourcesBeanDefinitionParser());
        this.registerBeanDefinitionParser("view-controller", new ViewControllerBeanDefinitionParser());
        this.registerBeanDefinitionParser("redirect-view-controller", new ViewControllerBeanDefinitionParser());
        this.registerBeanDefinitionParser("status-controller", new ViewControllerBeanDefinitionParser());
        this.registerBeanDefinitionParser("view-resolvers", new ViewResolversBeanDefinitionParser());
        this.registerBeanDefinitionParser("tiles-configurer", new TilesConfigurerBeanDefinitionParser());
        this.registerBeanDefinitionParser("freemarker-configurer", new FreeMarkerConfigurerBeanDefinitionParser());
        this.registerBeanDefinitionParser("groovy-configurer", new GroovyMarkupConfigurerBeanDefinitionParser());
        this.registerBeanDefinitionParser("script-template-configurer", new ScriptTemplateConfigurerBeanDefinitionParser());
        this.registerBeanDefinitionParser("cors", new CorsBeanDefinitionParser());
    }
}

//这样我们的每个标签都对应一个解析器
//比如mvc:interceptor  mvc:cors
//我们拿annotation-driven来讲

class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
    public static final String HANDLER_MAPPING_BEAN_NAME = RequestMappingHandlerMapping.class.getName();
    public static final String HANDLER_ADAPTER_BEAN_NAME = RequestMappingHandlerAdapter.class.getName();
    public static final String CONTENT_NEGOTIATION_MANAGER_BEAN_NAME = "mvcContentNegotiationManager";
    private static final boolean javaxValidationPresent;
    private static boolean romePresent;
    private static final boolean jaxb2Present;
    private static final boolean jackson2Present;
    private static final boolean jackson2XmlPresent;
    private static final boolean jackson2SmilePresent;
    private static final boolean jackson2CborPresent;
    private static final boolean gsonPresent;

    /*很多内容**/
    static {
        ClassLoader classLoader = AnnotationDrivenBeanDefinitionParser.class.getClassLoader();
        javaxValidationPresent = ClassUtils.isPresent("javax.validation.Validator", classLoader);
        romePresent = ClassUtils.isPresent("com.rometools.rome.feed.WireFeed", classLoader);
        jaxb2Present = ClassUtils.isPresent("javax.xml.bind.Binder", classLoader);
        jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) && ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader);
        jackson2XmlPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper", classLoader);
        jackson2SmilePresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.smile.SmileFactory", classLoader);
        jackson2CborPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.cbor.CBORFactory", classLoader);
        gsonPresent = ClassUtils.isPresent("com.google.gson.Gson", classLoader);
    }
}

//其实当我们写上这个标签之后我们对应的解析器就会有创建上面的这一些静态对象
//而RequestMappingHandlerMapping和RequestMappingHandlerAdapter是我们处理spring请求的两个核心类
//下面这一些其实就是当我们返回responsebody时,将对象转化为json的一些库
//我们的mvc会根据你的pom导入的jar包来创建对应的对象来做json解析
//例如jackson和gson(就是上面那些)默认支持解析gson和jackson的
//最后解析完还是会封装成BeanDefinition
//那么我们能不能写一个自定义标签让spring来帮我解析呢
//补充 xsd是我们标签的约束(标签的名字和属性)

//接下来开始自定义
//我们在我们的模块里面的resources里面定义一个META-INF目录
//我们先创建一个user.xsd
//我们希望  ----能通过这个自定义标签为我们创建User对象

<?xml version="1.0" encoding="UTF-8">
<schema xmlns="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://www.simon.com/schema/user"
    xmlns:tns = "http://www.simon.com/schema/user"
	elementFormDefault="qualified"
    //上面这些都是默认格式我也不懂为啥,user是指约束标签名为user
    <element name="user">
       <complexType>
        <attribute name="id" type="string"/>
        <attribute name="name" type="string"/>
        <attribute name="password" type="string"/>
      </complexType>
    </element>
    //规范了我们标签名以及属性不按照这样写会报错
 </schema>
        
 //然后在我们的resources里面创建spring.schema
//前面这个随便写,前面这个key是写在我们的applicationContext.xml里面的
//里面写上 http\://www.simon.com/schema/user.xsd=META-INF/user.xsd
//实际的xsd在META-INF里面
//然后我们在applicationContext的xmlns:xxx 这个可以随便写的只是个namespace的头
//我们就写xmlns:simon="http://www.simon.com/schema/user"
//在我们的schemaLocation写上我们spring.schemas里面定义的k即http\://www.simon.com/schema/user.xsd和http\://www.simon.com/schema/user(要写两个)
//xmlns的那个链接是对schemaLocation的常链(相同的),然后指定到我们下面的http\://www.simon.com/schema/user.xsd然后通过spring.schema来获取我们真是xsd规范文件路径
//在内容里面写上
//写上对应的自己实现的Handler
        
public class MyNameSpcaeHandler extends NameSpaceHandlerSupport{
    @Override
    public void init(){
        registerBeanDefinitionParser("user",new UserBeanDefinitionParser());
    }
    
}

public class UserBeanDefinitionParser extends AbstrctSingleBeanDifintionParser{
    //我们创建的是User类对象
    @Override
    protected Class<?> getBeanClass(Element element){
        retrun User.class;
    }
    //做解析
    @Override
    protected void doParse(Element element,BeanDefinitionBuilder builder){
        //获取标签值
        String name = element.getAttribute("name");
        String password = element.getAttribute("password");
        //增加beanDefinition属性值
        builder.addPropertyValue("name",name);
        builder.addPropertyValue("password",password);
    }
}
//然后在创建一个spring.handlers来解析这个标签
//写上 http\://www.simon.com/schema/user.xsd=com.simon.MyNameSpcaeHandler
//Spring知道了被MyNameSpcaeHandler处理器中对应的parser解析器来解析获得BeanDefinition
//我们运行就能够得到id为u的user并且属性为simon和123456

了解了整个流程,那么我们就要看看 parseCustomElement如何体现handler的作用的

@Nullable
    public BeanDefinition parseCustomElement(Element ele) {
        return this.parseCustomElement(ele, (BeanDefinition)null);
    }

    @Nullable
    public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
        //解析我们自定义的标签
        //获得我们的命名空间uri 是jdk提供的一个方法
        String namespaceUri = this.getNamespaceURI(ele);
        if (namespaceUri == null) {
            //没有uri就是没有自定义标签不需要介入直接返回null
            return null;
        } else {
            //这个方法就是获得我们的handler(有所体现,在我们的spring.handlers里面) 
            NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
            if (handler == null) {
                this.error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
                return null;
            } else {
                //我们spring工厂拿到handler根据init方法来获得对应标签的parser来对一个标签进行parse操作并封装成BeanDefinition
                return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
            }
        }
    }

你可能感兴趣的:(spring,java,后端)