本文使用的代码是: Spring 3.0
接触Spring也有很长一段时间了。但是,每次都是直接使用Spring直接提供的API,时间久了,自然也会想探索Spring里面的奥秘。今天上午,整理出了Spring的BeanFactory的一个体系结构(当然不是完整的,是以XmlFactory为最终目标),如下图(点击可到图片页面):
沿着XmlBeanFactory向上追溯,可以形成上面的BeanFactory体系结构。虽然不是很全面,但是如果这个图能理解透,我相信,Spring的BeanFactory就能理解透了。之后的系列我也会以这个图为中心,深入的去学习Spring的BeanFactory。
下面是对各个接口的理解。
BeanFactory
这个就是BeanFactory容器的最原始接口,也是spring容器提供的最原始客户端接口。
AutowireCapableBeanFactory
拥有自动装配能力的BeanFactory。这个BeanFactory并非是要用到应用中去的,在应用中要用,就用BeanFactory或者是ListableBeanFactory。这个接口更多的作用是用于和其他框架的结合,把不在Spring容器中的Bean加入到Spring容器声明周期管理中来。
需要注意的是,在Spring的ApplicationContext(Spring的应用容器)中,并没有实现这个接口,因为这个接口在应用中,确实很少用到。
不过,你可以通过ApplicationContext的getAutowireCapableBeanFactory()方法获得。或者,你也可以实现BeanFactoryAware(这个接口就是为了取得BeanFactory的),然后把BeanFactory转换成AutowireCapableBeanFactory。
HierarchicalBeanFactory
有层次的BeanFactory。如果实现了这个接口,可能就以为着你也需要实现ConfigurableBeanFactory。因为ConfigurableBeanFactory定义了设置父容器的方法,而HierarchicalBeanFactory的方法只有获得父容器的方法。而一般情况下,ConfigurableBeanFactory接口直接继承了HierarchicalBeanFactory。所以,它的实现,也是肯定要设置父容器的。
ListableBeanFactory
顾名思义,此BeanFactory是可以把容器中的bean循环枚举出来,而不是按照名字一个一个去取。
如果实现此接口的同时,也实现了HierarchicalBeanFactory,那么这个接口中的方法是不会去考虑父容器中的bean的。
需要注意的是:除了getBeanDefinitionCount和containsBeanDefinition方法之外,其他的方法最好不要直接在代码中调用,因为其实现可能会非常慢。
SingletonBeanRegistry
这个接口定义了一个注册singleton bean的容器。此接口可以被BeanFactory的实现实现,用来形成一个统一管理singleton bean的风格。ConfigurableBeanFactory接口就继承了此接口。
ConfigurableBeanFactory
此接口定义了BeanFactory的扩配置功能,几乎所有的beanFactory都会实现这个接口。
同样,此接口也不推荐在常见的应用代码中使用(还是推荐使用BeanFactory和ListableBeanFactory)。这个接口也赋予了BeanFactory可扩展的功能,
ConfigurableListableBeanFactory
又是可配置,又是Listable的BeanFactory,就可以实现这个接口。除了ConfigurableBeanFactory的功能之外,它还提供了访问和修改BeanDefinition,预实例化singletons。
AliasRegistry
管理别名的公共接口。
BeanDefinitionRegistry
注册BeanDefinition(Spring内部映射Bean的数据结构)的接口。
在这个体系中,接口部分,我就看了上面这些。下篇文章,我会深入去学习每个接口的实现,就是上图中右边的那些实现。
SimpleAliasRegistry实现的是AliasRegistry,也就是提供了别名的注册场所。
AliasRegistry是一个通用的管理别名的接口,BeanDefinitionAliasRegistry接口就是继承此接口。
此接口定义的方法(服务)也很简单:
- registerAlias 注册一个别名
- removeAlias 删除别名
- isAlias 判断是否是别名
- getAliases 获得一个名字的所有别名,以String数组的形式返回
那它的实现SimpleAliasRegistry,其内部采用了一个ConcurrentHashMap来进行别名的存储。因为方法的数量比较少,所以分别对这四个方法进行详读。
void registarAlias(String name, String alias)
首先,会看看 name 是否和 alias 相等,如果相等,就把存储器中的 alias 删除。
然后,其内部还定义了一个 allowAliasOverriding 的方法来判断是否允许覆盖。子类可以复写此方法,调整其策略。
void removeAlias(String alias)
很容易理解,但是这里需要注意,如果这个alias找不到,那么程序是会直接抛异常的,而不是默默的忽略。这个点在接口中也有提到的。
boolean isAlias(String name)
判断其是否是别名。
String[] getAliases(String name)
此方法会同步其内部的存储器,然后递归的进行查找,直到把所有的别名找出为止。
这里有个问题,为什么synchronized的对象,是这个内部的存储器呢?
经过一系列的研究,终于了解。原来,内部的存储器,是一个ConcurrentHashMap,而对这个存储器进行上锁,可以有效的防止在获取别名是,其他线程对存储器的修改。
接着学习 DefaultSingletonBeanRegistry。
一听名字,就知道这是一个SingletonBean注册的地方,此类也实现了SingletonBeanRegistry接口,继承了SimpleAliasRegistry。这也可以理解,DefaultSingletonBeanRegistry既有管理SingletonBean的功能,又提供了别名的功能,那当然可以继承SimpleAliasRegistry了。
DefaultSingletonBeanRegistry是一个通用的存储共享bean实例的地方,通过bean的名字获得bean。同时,它也给提供一次性bean的注册功能。
这个类的主要作用是,给BeanFactory的实现,提供基本的管理 singleton bean 实例功能。
这个类中,使用了三个主要的存储器(map)来分别存储 singletonObject,singletonFactory,earlySingletonObject。
当注册一个 singleton object 的时候,会在 singletonObject 的存储器中加入此 object,而在其他的两个存储器中移除。当然,这样的行为是可以在子类中去复写的。
在 getSingleton的时候,spring的默认实现是,先从 singleton object 的存储器中去寻找,如果找不到,再从 early singleton object 存储器中寻找,再找不到,那就在寻找对应的 singleton factory,造出所需的 singleton object,然后返回。
而 contains singleton 就是直接检查 singleton object 存储器了,其他的存储器不做检查。
而 get singleton counts 也是统计 singleton object 的数量。
看完了代码,再仔细想想,为什么这个类要使用三个存储器呢?
我想, singletonObjects 就是直观的存储着 singleton 的,而 singletonFactories 是存储的制造 singleton 的工厂,还有一个 earlySingletonObject, 在看了代码之后,我更觉得这是一个 singletonFactory 制造出来的 singleton 的缓存。
个人感觉,看spring,就像读一篇很好的文章,非常的流畅,而且也很值得细细品味。