容器的基本实现(三)

在开始之前,我才发现忘记说明了一些东西,这个系列完全是自己参看《spring源码深度解析》一书结合源码,总结而来,spring主要是3.0.5,如果这过程中有不正之处欢迎大家指正,在这过程中我也发现自己写的文章清晰度不高,这里会逐步提高,这里mark一些自己看到的好的学习spring的链接。

点击打开链接点击打开链接点击打开链接

继续上一篇的读取内容查看源码

  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)) {
                        this.parseDefaultElement(ele, delegate);
                    } else {
                        delegate.parseCustomElement(ele);
                    }
                }
            }
        } else {
            delegate.parseCustomElement(root);
        }

    }
进入parseDefaultElement方法,由方法名可知这里是解析默认的element,下面调用的和上一篇分析的方法一样
 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);
        }

    }
可以看出是对三种标签解析,我们先看Bean标签的解析
  protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        if (bdHolder != null) {
            bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);

            try {
                BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
            } catch (BeanDefinitionStoreException var5) {
                this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5);
            }

            this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
        }

    }

现在是2018年一月22日晚上九点半,一天上班又要干这,改那说实话我对程序员不免心生倦怠,不知道能坚持多久。

在进入parseBeanDefinitonElemet

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
        String id = ele.getAttribute("id");
        String nameAttr = ele.getAttribute("name");
        List<String> aliases = new ArrayList();
        if (StringUtils.hasLength(nameAttr)) {
            String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, ",; ");
            aliases.addAll((Collection)Arrays.asList(nameArr));
        }

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

        if (containingBean == null) {
                //保证beanNam的唯一性,id存在时为id,不然为name中的第一个
            this.checkNameUniqueness(beanName, aliases, ele);
        }

        /解析xml文件中的bean标签,并利用AbstractBeanDefinition用来保存其中的各个属性
        一、bean标签的属性
        scope:用来配置spring bean的作用域
        singleton:表示bean为单例的
        abstract:设置为true,将该bean仅仅作为模板使用,应用程序上下文不会试图预先初始化它
        lazy-init:设为true,延迟加载,该bean不会在ApplicationContext启动时提前被实例化,而是第一次向容器通过getBean索取bean时实例化。注:只对singleton的bean起作用
        autowire:自动装配
        dependency-check:依赖检查
        depends-on:表示一个bean的实例化依靠另一个bean先实例化
        autowire-candidate:设为false,容器在查找自动装配对象时,将不考虑该bean,即它不会被考虑作为其他bean自动装配的候选者,但是该bean本身可以使用自动装配来注入其他bean
        primary:该bean优先被注入
        init-method:初始化bean时调用的方法
        destory-method:容器销毁之前所调用的方法
        factory-method:当调用factory-method所指向的方法时,才开始实例化bean
        factory-bean:调用静态工厂方法的方式创建bean
        二、bean的子元素
        meta:元数据,当需要使用里面的信息时可以通过key获取
        lookup-method:获取器注入,是把一个方法声明为返回某种类型的bean但实际要返回的bean是在配置文件里面配置的
        replaced-method:可以在运行时调用新的方法替换现有的方法,还能动态的更新原有方法的逻辑
        constructor-arg:对bean自动寻找对应的构造函数,并在初始化的时候将设置的参数传入进去
        property:基本数据类型赋值
        qualifier:通过Qualifier指定注入bean的名称

        AbstractBeanDefinition beanDefinition = this.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);
                        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.isDebugEnabled()) {
                        this.logger.debug("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;
        }
    }
再解析bean标签之后,进入decorateBeanDefinitionIfRequired方法,此方法为bean标签下的元素进行解析,如果是自定义标签则调用其namespace否则不解析,原书对此方法的描述为装饰模式的调用?之后再进入BeanDefinitionReaderutils.registerBeanDefiniton方法,其中传入了bdholder,这之中具有bean的AbstaractBeanDefinition,其中获取的register为xmlBeanFactory
 public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
        String id = ele.getAttribute("id");
        String nameAttr = ele.getAttribute("name");
        List<String> aliases = new ArrayList();
        if (StringUtils.hasLength(nameAttr)) {
            String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, ",; ");
            aliases.addAll((Collection)Arrays.asList(nameArr));
        }

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

        if (containingBean == null) {
                //保证beanNam的唯一性,id存在时为id,不然为name中的第一个
            this.checkNameUniqueness(beanName, aliases, ele);
        }

        /解析xml文件中的bean标签,并利用AbstractBeanDefinition用来保存其中的各个属性
        一、bean标签的属性
        scope:用来配置spring bean的作用域
        singleton:表示bean为单例的
        abstract:设置为true,将该bean仅仅作为模板使用,应用程序上下文不会试图预先初始化它
        lazy-init:设为true,延迟加载,该bean不会在ApplicationContext启动时提前被实例化,而是第一次向容器通过getBean索取bean时实例化。注:只对singleton的bean起作用
        autowire:自动装配
        dependency-check:依赖检查
        depends-on:表示一个bean的实例化依靠另一个bean先实例化
        autowire-candidate:设为false,容器在查找自动装配对象时,将不考虑该bean,即它不会被考虑作为其他bean自动装配的候选者,但是该bean本身可以使用自动装配来注入其他bean
        primary:该bean优先被注入
        init-method:初始化bean时调用的方法
        destory-method:容器销毁之前所调用的方法
        factory-method:当调用factory-method所指向的方法时,才开始实例化bean
        factory-bean:调用静态工厂方法的方式创建bean
        二、bean的子元素
        meta:元数据,当需要使用里面的信息时可以通过key获取
        lookup-method:获取器注入,是把一个方法声明为返回某种类型的bean但实际要返回的bean是在配置文件里面配置的
        replaced-method:可以在运行时调用新的方法替换现有的方法,还能动态的更新原有方法的逻辑
        constructor-arg:对bean自动寻找对应的构造函数,并在初始化的时候将设置的参数传入进去
        property:基本数据类型赋值
        qualifier:通过Qualifier指定注入bean的名称

        AbstractBeanDefinition beanDefinition = this.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);
                        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.isDebugEnabled()) {
                        this.logger.debug("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;
        }
    }


        public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
        String beanName = definitionHolder.getBeanName();
        registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
        String[] aliases = definitionHolder.getAliases();
        if (aliases != null) {
            String[] var7 = aliases;
            int var6 = aliases.length;

            for(int var5 = 0; var5 < var6; ++var5) {
                String aliase = var7[var5];
                registry.registerAlias(beanName, aliase);
            }
        }

    }
   //注册beanDefinition
   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 {
                //校验beanDefinition中的methodOverrides中匹配的方法是否在beanDefinition中有方法
                ((AbstractBeanDefinition)beanDefinition).validate();
            } catch (BeanDefinitionValidationException var6) {
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var6);
            }
        }

        //全局变量,存有所有的beanDefinition
        Map var3 = this.beanDefinitionMap;
        synchronized(this.beanDefinitionMap) {
            Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
            if (oldBeanDefinition != null) {
                if (!this.allowBeanDefinitionOverriding) {
                    throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound.");
                }

                if (this.logger.isInfoEnabled()) {
                    this.logger.info("Overriding bean definition for bean '" + beanName + "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
                }
            } else {
                this.beanDefinitionNames.add(beanName);
                this.frozenBeanDefinitionNames = null;
            }

            this.beanDefinitionMap.put(beanName, beanDefinition);
            //
            this.resetBeanDefinition(beanName);
        }
    }




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值