美文网首页
2.spring 4 剖析-BeanDefinitionRegi

2.spring 4 剖析-BeanDefinitionRegi

作者: lrwin已经注册了 | 来源:发表于2018-06-14 16:29 被阅读0次

    前言

    上次我们已经聊过了BeanDefinition的实现原理,以及设计思路和如何使用它。
    spring工厂中使用的bean实例就是BeanDefinition.

    这次的主题就是如何将BeanDefinition进行注册,这次要分析的接口是:BeanDefinitionRegistry

    类图

    以BeanDefinitionRegistry为中心,展开的类图:

    BeanDefinitionRegistry类图

    源码分析

    BeanDefinitionRegistry

    
    /**
     * 
     * Spring的核心实现是 DefaultListableBeanFactory 和 GenericApplicationContext
    *
      * @author Juergen Hoeller
     * @since 26.11.2003
     * @see org.springframework.beans.factory.config.BeanDefinition
     * @see AbstractBeanDefinition
     * @see RootBeanDefinition
     * @see ChildBeanDefinition
     * @see DefaultListableBeanFactory
     * @see org.springframework.context.support.GenericApplicationContext
     * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
     * @see PropertiesBeanDefinitionReader
     */
    public interface BeanDefinitionRegistry extends AliasRegistry {
        void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
                throws BeanDefinitionStoreException;
        void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
        BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
        boolean containsBeanDefinition(String beanName);
        String[] getBeanDefinitionNames();
        int getBeanDefinitionCount();
        boolean isBeanNameInUse(String beanName);
    }
    

    AliasRegistry这个接口的意思是可以给BeanDefinition起个别名,然后注册使用。

    spring 提供给了我们一个简单的类进行测试--SimpleBeanDefinitionRegistry

    SimpleBeanDefinitionRegistry

    public class SimpleBeanDefinitionRegistry extends SimpleAliasRegistry implements BeanDefinitionRegistry {
        private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);
        @Override
        public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
                throws BeanDefinitionStoreException {
    
            Assert.hasText(beanName, "'beanName' must not be empty");
            Assert.notNull(beanDefinition, "BeanDefinition must not be null");
            this.beanDefinitionMap.put(beanName, beanDefinition);
        }
    //其他代码省略
    }
    

    它仅仅使用了Map进行了存储。

    可以做个小实验试一下:

    public class Test {
    
        public static void main(String[] args) throws Exception {
            BeanDefinitionRegistry beanDefinitionRegistry = new SimpleBeanDefinitionRegistry();
            AnnotatedGenericBeanDefinition genericBeanDefinition = new AnnotatedGenericBeanDefinition(Test.class);
            beanDefinitionRegistry.registerBeanDefinition("springBean",genericBeanDefinition);
            System.out.println(beanDefinitionRegistry.isBeanNameInUse("springBean"));
        }
    }
    

    输出:

    true
    

    DefaultListableBeanFactory

    spring 推荐给我们,DefaultListableBeanFactory和GenericApplicationContext才是核心。

    我们看一下DefaultListableBeanFactory:

    public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
            implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);
    
    @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 (this.logger.isInfoEnabled()) {
                        this.logger.info("Overriding bean definition for bean '" + beanName +
                                "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
                    }
                }
            }
            else {
                this.beanDefinitionNames.add(beanName);
                this.manualSingletonNames.remove(beanName);
                this.frozenBeanDefinitionNames = null;
            }
            this.beanDefinitionMap.put(beanName, beanDefinition);
    
            if (oldBeanDefinition != null || containsSingleton(beanName)) {
                resetBeanDefinition(beanName);
            }
        }
    //其他方法省略
    }
    

    可以看出来它依然使用了Map进行存储(变量是beanDefinitionMap),只不过验证流程比较缜密了。

    GenericApplicationContext

    public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
        private final DefaultListableBeanFactory beanFactory;
        private ResourceLoader resourceLoader;
        private boolean refreshed = false;
        public GenericApplicationContext() {
            this.beanFactory = new DefaultListableBeanFactory();
        }
            @Override
        public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
                throws BeanDefinitionStoreException {
    
            this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
        }
    //其他代码省略
    }
    

    看到构造方法中的this.beanFactory = new DefaultListableBeanFactory(); 就发现,其实GenericApplicationContext使用的注册bean依然是使用DefaultListableBeanFactory的实现原理。

    相关文章

      网友评论

          本文标题:2.spring 4 剖析-BeanDefinitionRegi

          本文链接:https://www.haomeiwen.com/subject/injyeftx.html