美文网首页
BeanDefinitionRegistry-源码分析

BeanDefinitionRegistry-源码分析

作者: 想起个帅气的头像 | 来源:发表于2020-10-24 15:08 被阅读0次

    BeanDefinitionRegistry

    摘要

    见名知义,BeanDefinitionRegistry就是用于将BeanDefinition注册到spring容器中,即添加到beanDefinitionMap(Map<String, BeanDefinition>)。

    类图

    BeanDefinitionRegistry.png

    源码分析

    BeanDefinitionRegistry是一个接口,定义了一系列对BeanDefinition的操作接口,如注册、移除、返回等等,需要各子类实现BeanDefinition注册的动作。

    /**
     * Interface for registries that hold bean definitions, for example RootBeanDefinition
     * and ChildBeanDefinition instances. Typically implemented by BeanFactories that
     * internally work with the AbstractBeanDefinition hierarchy.
     *
     * <p>This is the only interface in Spring's bean factory packages that encapsulates
     * <i>registration</i> of bean definitions. The standard BeanFactory interfaces
     * only cover access to a <i>fully configured factory instance</i>.
     *
     * <p>Spring's bean definition readers expect to work on an implementation of this
     * interface. Known implementors within the Spring core are DefaultListableBeanFactory
     * and GenericApplicationContext.
     */
    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();
        //用于检测beanName是否已经被其他BeanDefinition使用
        boolean isBeanNameInUse(String beanName);
    
    

    可以看到BeanDefinitionRegistry下有三个实现类:

    SimpleBeanDefinitionRegistry

    这个Registry是spring提供的给用户测试,写demo的实现,很简单,这个不多讨论。

    GenericApplicationContext
    public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry { ... }
    

    GenericApplicationContext分别继承了AbstractApplicationContext和实现了BeanDefinitionRegistry
    继承AbstractApplicationContext为后续的各种ApplicationContext的实现子类提供了统一父类,而BeanDefinitionRegistry的实现则是由DefaultListableBeanFactory来完成。

    DefaultListableBeanFactory

    我们将着重分析一下DefaultListableBeanFactory中的registerBeanDefinition实现。

    @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 existingDefinition = this.beanDefinitionMap.get(beanName);
            if (existingDefinition != null) {
                if (!isAllowBeanDefinitionOverriding()) {
                    throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
                }
                else if (existingDefinition.getRole() < beanDefinition.getRole()) {
                    // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
                    if (logger.isInfoEnabled()) {
                        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 (logger.isDebugEnabled()) {
                        logger.debug("Overriding bean definition for bean '" + beanName +
                                "' with a different definition: replacing [" + existingDefinition +
                                "] with [" + beanDefinition + "]");
                    }
                }
                else {
                    if (logger.isTraceEnabled()) {
                        logger.trace("Overriding bean definition for bean '" + beanName +
                                "' with an equivalent definition: replacing [" + existingDefinition +
                                "] 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进行修改,会导致ConcurrentModificationException
                        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 (existingDefinition != null || containsSingleton(beanName)) {
                resetBeanDefinition(beanName);
            }
        }
    
    
    1. 首先对BeanDefinition进行有效性校验, validate()判断hasMethodOverrides和getFactoryMethodName不能同时存在。
      lookup-method 和 replaced-method 注解标注的方法都会被保存在methodOverrides 集合中,当bean在实例化时如果检测到有methodOverrides存在,则会动态为当前bean生成代理并使用对应拦截器对bean进行增强。
         public void validate() throws BeanDefinitionValidationException {
            if (hasMethodOverrides() && getFactoryMethodName() != null) {
                throw new BeanDefinitionValidationException(
                        "Cannot combine static factory method with method overrides: " +
                        "the static factory method must create the instance");
            }
    
            if (hasBeanClass()) {
                prepareMethodOverrides();
            }
        }
    

    FactoryMethod则是一种通过工厂方法创建bean的一种方式,分为静态工厂方法和动态工厂方法

    //静态工厂,不需要实例化工厂本身,通过静态方法创建bean
    <bean id="beanA" class="com.xxx.FactoryA" factory-method="createA"></bean> 
    
    //动态工厂,需要实例化工厂,根据工厂bean来创建需要的bean
    <bean id="factoryA" class="com.xxx.Factory"></bean> 
    <bean id="beanA"  factory-bean="factoryA" factory-method="createA"></bean> 
    
    1. 通过判断该beanName是否已经存在。
      a. 已经存在BeanDefinition,先判断是否允许覆盖,允许则输出一系列日志,put新的beanDefinition
      b. 如果不存在,先判断是否已经有bean被创建过,即是否已经进入运行阶段。如果还是启动注册阶段,可以直接put,否则就需要加锁。

    DefaultListableBeanFactory源码分析将重点分析BeanFactory的一系列实现。

    相关文章

      网友评论

          本文标题:BeanDefinitionRegistry-源码分析

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