Spring源码DefaultListableBeanFactory

 2023-02-08
原文作者:雷小鸿 原文地址:https://juejin.cn/post/7024800237302579236

本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。

DefaultListableBeanFactory

完全看不懂这个类那么先看这个类的继承关系。看先和他有关的类,再一个个去研究。

DefaultListableBeanFactory继承了AbstractAutowireCapableBeanFactory

DefaultListableBeanFactory实现了ConfigurableListableBeanFactory和BeanDefinitionRegistry

AbstractAutowireCapableBeanFactory是个被abstract的修饰抽象类,并继承了AbstractBeanFactory和实现了AutowireCapableBeanFactory

AbstractBeanFactory一样是个被abstract的修饰抽象类,并继承了FactoryBeanRegistrySupport和实现了ConfigurableBeanFactory

FactoryBeanRegistrySupport一样是被abstract的修饰抽象类,并继承自DefaultSingletonBeanRegistry

DefaultSingletonBeanRegistry是个普通类,继承自SimpleAliasRegistry并实现了SingletonBeanRegistry

SimpleAliasRegistry是个普通的类实现了AliasRegistry,AliasRegistry是个最上层的接口

SingletonBeanRegistry也是个最上层的接口

ConfigurableBeanFactory是个接口,继承自HierarchicalBeanFactory和SingletonBeanRegistry

HierarchicalBeanFactory是个接口,继承自BeanFactory,BeanFactory是个最上层的接口

AutowireCapableBeanFactory是个接口,继承自BeanFactory

ConfigurableListableBeanFactory是个接口,继承自ListableBeanFactory和AutowireCapableBeanFactory和ConfigurableBeanFactory接口

ListableBeanFactory和AutowireCapableBeanFactory都继承自BeanFactory接口

ConfigurableBeanFactory接口又继承自HierarchicalBeanFactory和SingletonBeanRegistry接口

BeanDefinitionRegistry接口继承自AliasRegistry接口

乱不乱 都快成一锅粥了那么这就是一堆面向接口的编程思想组成的一堆接口,那么去找找DefaultListableBeanFactory的继承关系。

202301012111180041.png 一共19个类我们一个一个来研究这些类都是干啥的。

接口AliasRegistry实现类SimpleAliasRegistry

定义了对Alias的增删改查操作。

202301012111201302.png

方法1

void registerAlias(String name, String alias)第一个参数是规范名称,第二个参数是别名,意思就是给name注册一个别名,在SimpleAliasRegistry接口中的实现如下。

202301012111212943.png 逻辑是用一个map,注意map的线程安全的ConcurrentHashMap,存name和alias,用alias当做key,name是value。

  • 先对name和alias非空判断,对map的操作是加了synchronized,保证了原子性操作。

  • 然后判断name和alias值是否相等如果相等在map中删除key是alias的值。

  • 如果不相等去map取值,如果取到值说明已经存在别名,直接退出。

  • !allowAliasOverriding()是否允许别名被重写,即一个name存在多个alias。

  • checkForAliasCircle(name, alias)的方法主要逻辑见下图:内容是确定这次注册的name,是否已经被当成别名被占用了,注意这个函数的name调用传递的是是主函数的alias,alias传递的是name,上层调用是这样的asAlias(alias, name),举例说明就是比如name是LXH别名是H,我用H这个别名去map查找是不存在H这个别名的。但是反过来Map存在name是H别名是LXH的键值对。这种情况就是循环注册了会抛出异常。

    202301012111224594.png

  • 上述检查通过将将别名和规范名称放入map中aliasMap.put(alias, name)

方法2

removeAlias(String alias):直接调用remove()方法,别名不存在抛出异常。如图:

202301012111231075.png

方法3

isAlias(String name)判断别名是否存在。如图:

202301012111241776.png

方法4

getAliases(String name)返回给定规范名称的所有别名,如果没有返回空数组。

202301012111249397.png

接口SingletonBeanRegistry实现类SingletonBeanRegistry

定义了对单例的注册和获取

方法1

registerSingleton(String beanName, Object singletonObject)在bean注册表中将给定的现有对象注册为单例(singleton),beanName为bean的名称,singletonObject为现有的单例对象。

  • 代码块是synchronized修饰的, 往对象singletonObjects直接放单例对象Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256),key是单例对象的name,value是单例对象的实例,

  • 从单例工厂中移除当前单例对象Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16)为单例工厂

  • 从早期的单例缓存对象中移除当前单例对象earlySingletonObjects,Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16)这个为啥初始大小是16,singletonObjects是256要我设计我可能搞一样的初始大小了,留以后研究。

  • 把注册成功的单例名称放到一个set集合中去Set<String> registeredSingletons = new LinkedHashSet<>(256)

    202301012111257498.png

方法2

getSingleton(String beanName),通过beanName获取注册的单例对象

  • 直接在注册成功的缓存singletonObjects对象map中get实例value,如果得到直接返回。

  • 如果singletonObjects对象不存在单例对象,那么检查是否是正在注册单例缓存对象earlySingletonObjects中。如果存在也直接返回。

  • 加synchronized代码块。

  • 如果还是为null,然后又去singletonObjects对象map中获取了一遍。

  • 如果仍然为null,再去earlySingletonObjects对象map中获取一遍,这个很像单例的double check,如果是多线程操作,再第一和二步的时候,如果有其他线程把当前获取的对象注册成功,就需要在同步的代码块中再获取一次。

  • 如果结果还是null,那就再根据beanName去单例工厂中获取。

  • 如果已经在单例工厂中了,那么就从工厂中获取该实例,并将该实例放入earlySingletonObjects对象中,并从singletonFactories工厂中删除掉。

  • 没有想明白为什么往earlySingletonObjects放一遍,而不继续往singletonObjects缓存对象放。

    202301012111265649.png

方法3

containsSingleton(String beanName),判断缓存的map中是否存在该单例对象名称,注意只判断对象为singletonObjects的map中,判断代码为singletonObjects.containsKey(beanName) 。

方法4

String[] getSingletonNames()这个更简单,原文注释为Return the names of singleton beans registered in this registry不做解释简单明了。

方法5

int getSingletonCount()返回注册的单例总个数,原代码注释Return the number of singleton beans registered in this registry注意源代码的意思是此方法只检查手动注册的bean个数。未注册成功不算返回的是registeredSingletons的size。

方法6

getSingletonMutex()直接把singletonObjects对象return回去了,这什么意思呢?源码的注释是Return the singleton mutex used by this registry (for external collaborators)意思大概是返回该注册表使用的单例互斥锁。

总结

学习了对Alias的增删改查操作和对单例的注册和获取