likes
comments
collection
share

IOC 核心概念——BeanDefinition

作者站长头像
站长
· 阅读数 47

概念

A BeanDefinition describes a bean instance, which has property values,constructor argument values, and further information supplied by concrete implementations.

一个 BeanDefinition 描述了一个 Bean 实例,该实例包含属性值、构造方法参数值以及更多实现信息。

BeanDefinition 是 Spring 内部的一个接口,定义了 Bean 描述的基本规范。实际上就是对象在容器中的抽象。通过 BeanDefinition 容器能够方便地对 Bean 进行管理。对于单例的 Bean,在第一次 getBean 的时候读取 BeanDefinition 获取定义,然后再创建和初始化 Bean,并缓存起来。对于原型的 Bean,在每一次 getBean 的时候都需要使用 BeanDefinition 的数据进行创建和初始化,不会缓存 Bean

BeanDefinition 接口的主要方法覆盖了 Spring 构造 Bean 需要的所有信息:

  • getBeanClassName:获取 Bean 的类名称;
  • isLazyInit:是否懒加载;
  • getFactoryBeanName:获取对应的 FactoryBean 的名称;
  • getConstructorArgumentValues:获取构造器参数,可以通过 xml、注解注入;
  • getPropertyValues:获取属性参数,可以通过 xml、注解注入。
  • ............

继承体系

BeanDefinition 是一个接口,它有多个实现类,这些实现类分别描述不同类型的 Bean

IOC 核心概念——BeanDefinition

注册 BeanDifinition

将定义 bean 的资源文件解析成 BeanDefinition 后需要将其注入容器中,这个过程由 BeanDefinitionRegistry 来完成。

BeanDefinitionRegistry:向注册表中注册 BeanDefinition 实例,完成注册的过程。

BeanDefinitionRegistry 是 Spring 的 Bean 工厂包中唯一封装 BeanDefinition 注册的接口

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

public interface BeanDefinitionRegistry extends AliasRegistry {

   /**
    * Register a new bean definition with this registry.
    * Must support RootBeanDefinition and ChildBeanDefinition.
    */
   void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
         throws BeanDefinitionStoreException;

   /**
    * Remove the BeanDefinition for the given name.
    */
   void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

   /**
    * Return the BeanDefinition for the given bean name.
    */
   BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

   /**
    * Check if this registry contains a bean definition with the given name.
    */
   boolean containsBeanDefinition(String beanName);

   /**
    * Return the names of all beans defined in this registry.
    */
   String[] getBeanDefinitionNames();

   /**
    * Return the number of beans defined in the registry.
    */
   int getBeanDefinitionCount();

   /**
    * Determine whether the given bean name is already in use within this registry,
    * i.e. whether there is a local bean or alias registered under this name.
    */
   boolean isBeanNameInUse(String beanName);
}

继承体系

BeanDefinitionRegistry 继承了 AliasRegistry 接口,其核心子类有三个:SimpleBeanDefinitionRegistryDefaultListableBeanFactoryGenericApplicationContext

IOC 核心概念——BeanDefinition

AliasRegistry

用于别名管理的通用型接口,作为 BeanDefinitionRegistry 的顶层接口。  AliasRegistry 定义了一些别名管理的方法。

public interface AliasRegistry {

   /**
    * Given a name, register an alias for it.
    */
   void registerAlias(String name, String alias);

   /**
    * Remove the specified alias from this registry.
    */
   void removeAlias(String alias);

   /**
    * Determine whether this given name is defines as an alias
    */
   boolean isAlias(String name);

   /**
    * Return the aliases for the given name, if defined.
    */
   String[] getAliases(String name);
}

SimpleBeanDefinitionRegistry

SimpleBeanDefinitionRegistryBeanDefinitionRegistry 一个简单的实现,它还继承 SimpleAliasRegistryAliasRegistry 的简单实现),它仅仅只提供注册表功能,无工厂功能 。

SimpleBeanDefinitionRegistry 使用 ConcurrentHashMap 来存储注册的 BeanDefinition

public class SimpleBeanDefinitionRegistry extends SimpleAliasRegistry implements BeanDefinitionRegistry {

   /** Map of bean definition objects, keyed by bean name. */
   private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(64);

   @Override
   public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
         throws BeanDefinitionStoreException {
     
      // ......
      
      this.beanDefinitionMap.put(beanName, beanDefinition);
   }
  
   // ......
}

DefaultListableBeanFactory

DefaultListableBeanFactory 是一个基于 BeanDefinition 元数据的完整 bean 工厂 。所以相对于 SimpleBeanDefinitionRegistry 而言,DefaultListableBeanFactory 则是一个具有注册功能的完整 bean 工厂。它同样是用 ConcurrentHashMap 数据结构来存储注册的 BeanDefinition


/** Map of bean definition objects, keyed by bean name. */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
      throws BeanDefinitionStoreException {
      
      // ......
      
      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;
      
      // ......
}

GenericApplicationContext

对于 GenericApplicationContext ,其实现注册、注销功能都是委托 给 DefaultListableBeanFactory 实现的。


private final DefaultListableBeanFactory beanFactory;

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
      throws BeanDefinitionStoreException {

   this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
}
转载自:https://juejin.cn/post/7077806547643924517
评论
请登录