基本概念
BeanDefinitionRegistry ,該類的作用主要是向注冊表中注冊 BeanDefinition 實例,完成 注冊的過程。
它的接口定義如下:
public interface BeanDefinitionRegistry extends AliasRegistry { // 關鍵 -> 往注冊表中注冊一個新的 BeanDefinition 實例 void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionStoreException; // 移除注冊表中已注冊的 BeanDefinition 實例 void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException; // 從注冊中取得指定的 BeanDefinition 實例 BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException; // 判斷 BeanDefinition 實例是否在注冊表中(是否注冊) boolean containsBeanDefinition(String beanName); // 取得注冊表中所有 BeanDefinition 實例的 beanName(標識) String[] getBeanDefinitionNames(); // 返回注冊表中 BeanDefinition 實例的數量 int getBeanDefinitionCount(); // beanName(標識)是否被占用 boolean isBeanNameInUse(String beanName); }
再來看它的繼承關系:
2.DefaultListableBeanFactory
該類是 BeanDefinitionRegistry 接口的基本實現類,但同時也實現其他了接口的功能,這里只探究下其關於注冊 BeanDefinition 實例的相關方法 。
首先來看它的成員變量:
// 關鍵-> 注冊表,由 BeanDefinition 的標識 (beanName) 與其實例組成 private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, bean>(64); // 標識(beanName)集合 private final List<String> beanDefinitionNames = new ArrayList<String>(64);
再來看 BeanDefinitionReaderUtils 的 registerBeanDefinition 方法。該方法的主要作用是調用注冊器(DefaultListableBeanFactory)完成注冊過程。
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 校驗 ((AbstractBeanDefinition) beanDefinition).validate(); }catch (BeanDefinitionValidationException ex) { // 拋出異常... } } BeanDefinition oldBeanDefinition; oldBeanDefinition = this.beanDefinitionMap.get(beanName); if (oldBeanDefinition != null) { if (!isAllowBeanDefinitionOverriding()) { // 拋出異常... }else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) { // 日志輸出... } else if (!beanDefinition.equals(oldBeanDefinition)) { // 日志輸出... } else { // 日志輸出... } }else { // 添加標識進 List this.beanDefinitionNames.add(beanName); this.manualSingletonNames.remove(beanName); this.frozenBeanDefinitionNames = null; } // 關鍵 -> 添加進 map this.beanDefinitionMap.put(beanName, beanDefinition); if (oldBeanDefinition != null || containsSingleton(beanName)) { resetBeanDefinition(beanName); } }
觀察代碼可以發現該方法最重要的步驟其實就是:
this.beanDefinitionMap.put(beanName, beanDefinition);
也就是向注冊表中(beanDefinitionMap)添加 BeanDefinition 實例,完成注冊的過程。