文档章节

spring源码解析六

writeademo
 writeademo
发布于 2017/02/02 16:36
字数 1200
阅读 78
收藏 0

AbstractBeanDefinition属性

Xml文档到GenericBeanDefinition的转换,xml中所有的配置都可以在GenericBeanDefinition的实例中找到了对应的配置

GenericBeanDefiniton只是子类的实现

    private volatile Object beanClass;

 

    private String scope = SCOPE_DEFAULT;

 

    private boolean abstractFlag = false;

 

    private boolean lazyInit = false;

 

    private int autowireMode = AUTOWIRE_NO;

 

    private int dependencyCheck = DEPENDENCY_CHECK_NONE;

 

    private String[] dependsOn;

 

    private boolean autowireCandidate = true;

 

    private boolean primary = false;

 

    private final Map<String, AutowireCandidateQualifier> qualifiers = new LinkedHashMap<>(0);

 

    private Supplier<?> instanceSupplier;

 

    private boolean nonPublicAccessAllowed = true;

 

    private boolean lenientConstructorResolution = true;

 

    private String factoryBeanName;

 

    private String factoryMethodName;

 

    private ConstructorArgumentValues constructorArgumentValues;

 

    private MutablePropertyValues propertyValues;

 

    private MethodOverrides methodOverrides = new MethodOverrides();

 

    private String initMethodName;

 

    private String destroyMethodName;

 

    private boolean enforceInitMethod = true;

 

    private boolean enforceDestroyMethod = true;

 

    private boolean synthetic = false;

 

    private int role = BeanDefinition.ROLE_APPLICATION;

 

    private String description;

 

    private Resource resource;

 

 

    /**

     * Create a new AbstractBeanDefinition with default settings.

     */

    protected AbstractBeanDefinition() {

        this(null, null);

       }

 

 

解析默认标签中的自定义标签元素

上段中解析了BeanDefinitionHolder bdHolder=delegate.parseBeanDefinitionElement(ele)

接下来分析bdHolder=delegate.decorateBeanDefinitionRequired(ele,bdHolder)

作用<bean id=”test” class=”test.MyClass”>

                   <mybean:user username=”aaa”>

</bean>

 

Bean使用的是默认的标签配置,其中的子元素使用了自定义的配置,这句代码就会起作用了。一种是默认的解析,一种是自定义的解析。

    public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder) {

        return decorateBeanDefinitionIfRequired(ele, definitionHolder, null);

       }

第三个参数设置为空,第三个参数是父类bean,当对某个配置进行分析时,这里需要传递父类beanDefinition

 

public BeanDefinitionHolder decorateBeanDefinitionIfRequired(

            Element ele, BeanDefinitionHolder definitionHolder, BeanDefinition containingBd) {

 

        BeanDefinitionHolder finalDefinition = definitionHolder;

 

        // Decorate based on custom attributes first.

        NamedNodeMap attributes = ele.getAttributes();

        for (int i = 0; i < attributes.getLength(); i++) {

            Node node = attributes.item(i);

            finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);

        }

 

        // Decorate based on custom nested elements.

        NodeList children = ele.getChildNodes();

        for (int i = 0; i < children.getLength(); i++) {

            Node node = children.item(i);

            if (node.getNodeType() == Node.ELEMENT_NODE) {

                finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);

            }

        }

        return finalDefinition;

       }

 

public BeanDefinitionHolder decorateIfRequired(

            Node node, BeanDefinitionHolder originalDef, BeanDefinition containingBd) {

 

        String namespaceUri = getNamespaceURI(node);

        if (!isDefaultNamespace(namespaceUri)) {

            NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);

            if (handler != null) {

                return handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd));

            }

            else if (namespaceUri != null && namespaceUri.startsWith("http://www.springframework.org/")) {

                error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", node);

            }

            else {

                // A custom namespace, not to be handled by Spring - maybe "xml:...".

                if (logger.isDebugEnabled()) {

                    logger.debug("No Spring NamespaceHandler found for XML schema namespace [" + namespaceUri + "]");

                }

            }

        }

        return originalDef;

       }

 

    public String getNamespaceURI(Node node) {

        return node.getNamespaceURI();

       }

    public boolean isDefaultNamespace(String namespaceUri) {

        return (!StringUtils.hasLength(namespaceUri) || BEANS_NAMESPACE_URI.equals(namespaceUri));

       }

首先获得属性或者元素的命名空间,以此来判断该元素或属性是否适用于自定义标签的解析条件,找出自定义类型所对应的namespaceHandler并进行进一步解析。

注册解析的BeanDefinition

对于配置文件,解析完了,装饰也装饰玩了,对于得到的beanDefinition已经可以满足后续的使用要求了,唯一的工作就是注册了。

BeanDefinitionReaderUtils.registerBeanDefintion(bdHolder,getReaderContext().getRegistry())

    /**

     * 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 alias : aliases) {

                registry.registerAlias(beanName, alias);

            }

        }

    }

 

Registry实例中注册分成两部分,通过beanName的注册和通过别名的注册。

通过beanName注册BeanDefinition

BeanDefinitionRegistry接口

package org.springframework.beans.factory.support;

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory

        implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {

    //---------------------------------------------------------------------

    // Implementation of BeanDefinitionRegistry interface

    //---------------------------------------------------------------------

 

    @Override

    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 ex) {

                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,

                        "Validation of bean definition failed", ex);

            }

        }

 

        BeanDefinition oldBeanDefinition;

 

        oldBeanDefinition = this.beanDefinitionMap.get(beanName);

        if (oldBeanDefinition != null) {

            if (!isAllowBeanDefinitionOverriding()) {

                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,

                        "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +

                        "': There is already [" + oldBeanDefinition + "] bound.");

            }

            else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {

                // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE

                if (this.logger.isWarnEnabled()) {

                    this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +

                            "' with a framework-generated bean definition: replacing [" +

                            oldBeanDefinition + "] with [" + beanDefinition + "]");

                }

            }

            else if (!beanDefinition.equals(oldBeanDefinition)) {

                if (this.logger.isInfoEnabled()) {

                    this.logger.info("Overriding bean definition for bean '" + beanName +

                            "' with a different definition: replacing [" + oldBeanDefinition +

                            "] with [" + beanDefinition + "]");

                }

            }

            else {

                if (this.logger.isDebugEnabled()) {

                    this.logger.debug("Overriding bean definition for bean '" + beanName +

                            "' with an equivalent definition: replacing [" + oldBeanDefinition +

                            "] with [" + beanDefinition + "]");

                }

            }

            this.beanDefinitionMap.put(beanName, beanDefinition);

        }

        else {

            if (hasBeanCreationStarted()) {

                // Cannot modify startup-time collection elements anymore (for stable iteration)

                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;

                    if (this.manualSingletonNames.contains(beanName)) {

                        Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);

                        updatedSingletons.remove(beanName);

                        this.manualSingletonNames = updatedSingletons;

                    }

                }

            }

            else {

                // Still in startup registration phase

                this.beanDefinitionMap.put(beanName, beanDefinition);

                this.beanDefinitionNames.add(beanName);

                this.manualSingletonNames.remove(beanName);

            }

            this.frozenBeanDefinitionNames = null;

        }

 

        if (oldBeanDefinition != null || containsSingleton(beanName)) {

            resetBeanDefinition(beanName);

        }

    }

}

Bean的注册上,进行了几步:

1AbstractBeanDefinition的校验,在解析xml时进行过校验,之前的校验是对xml格式的校验,而此校验针对的是AbstractBeanDefinitionmethodOverrides属性的

2beanName已经注册的情况进行处理,如果不允许覆盖bean,则抛出异常

3加入map缓存

4清除解析之前留下的对应beanName缓存

 

 

通过别名注册beanDefinition

public class SimpleAliasRegistry implements AliasRegistry {

 

    /** Map from alias to canonical name */

    private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);

 

 

    @Override

    public void registerAlias(String name, String alias) {

        Assert.hasText(name, "'name' must not be empty");

        Assert.hasText(alias, "'alias' must not be empty");

        if (alias.equals(name)) {

            this.aliasMap.remove(alias);

        }

        else {

            String registeredName = this.aliasMap.get(alias);

            if (registeredName != null) {

                if (registeredName.equals(name)) {

                    // An existing alias - no need to re-register

                    return;

                }

                if (!allowAliasOverriding()) {

                    throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" +

                            name + "': It is already registered for name '" + registeredName + "'.");

                }

            }

            checkForAliasCircle(name, alias);

            this.aliasMap.put(alias, name);

        }

    }

处理过程

1 alais和beanname相同的情况,删除

2 alias覆盖处理

3.alias循环检测,如存在A->B,再出现A->C->B则抛出异常

4 注册alias

 

通知监听器解析及注册完成

getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder))完成此工作。

© 著作权归作者所有

writeademo
粉丝 25
博文 624
码字总数 226691
作品 0
东城
私信 提问
springmvc源码解析合集

更多精彩源码解析文章请关注”天河聊架构“微信公众号。 springmvc源码解析之组件介绍 springmvc源码解析之配置加载SpringServletContainerInitializer springmvc源码解析之配置加载Context...

天河2018
03/27
0
0
Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密...

小致dad
2018/08/03
0
0
Spring 源码解读 推荐流程

Spring源代码解析(一):IOC容器:http://www.javaeye.com/topic/86339 Spring源代码解析(二):IoC容器在Web容器中的启动:http://www.javaeye.com/topic/86594 Spring源代码解析(三):Sprin...

2k10
2015/04/02
0
0
spring源码-bean之初始化-1

  一、spring的IOC控制反转:控制反转——Spring通过一种称作控制反转(IOC)的技术促进了松耦合。当应用了IOC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建...

小不点丶
2018/08/09
0
0
Spring源码解析系列之IOC容器(一)

前言 实际上我所有的博客都是原来对原来印象笔记里笔记内容的加工,关于Spring源码自己已经解析了很多遍,但是时间长总是忘记,写一篇博客权当加强记忆,也算再次学习下大师们的设计思想,思...

后厂村老司机
2018/06/02
0
0

没有更多内容

加载失败,请刷新页面

加载更多

分布式架构 实现分布式锁的常见方式

一、我们为什么需要分布式锁? 在单机时代,虽然不需要分布式锁,但也面临过类似的问题,只不过在单机的情况下,如果有多个线程要同时访问某个共享资源的时候,我们可以采用线程间加锁的机制...

太猪-YJ
41分钟前
3
0
GitLab Docker 安装记录

安装环境 环境Centos7.4 64 1.拉取镜像文件 docker pull gitlab/gitlab-ce:latest 2.docker 安装 git.zddts.com 为访问域名或换成可以访问的IP docker run -d --hostname git.***.com -p ......

侠者圣
今天
0
0
部署kubernates dashboard

参考官方文档: https://github.com/kubernetes/dashboard 直接部署官方默认的dashboard: kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/r......

猫海豚
今天
0
0
Docker中Redis的安装

一、下载镜像 docker pull redis 二、创建外挂目录及配置 mkdir /opt/docker/redismkdir /opt/docker/redis/confmkdir /opt/docker/redis/data 三、安装 docker run -d --name compose_r......

闊苡訆涐囍醣
今天
0
0
JNI内存泄露处理方法汇总

在c++中new的对象,如果不返回java,必须用release掉,否则内存泄露。包括NewStringUTF,NewObject。如果返回java不必release,java会自己回收。   jstring jstr = env->NewStringUTF((*p)....

shzwork
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部