Spring5源码浅析(三)—ConfigurableBeanFactory
在上一篇中,我们分析了HierarchicalBeanFactory和ListableBeanFactory这两个接口的情况,然后我们知道ListableBeanFactory主要是扩展了一些对工厂内的Bean进行汇总统计和迭代的一些接口,而HierarchicalBeanFactory接口则是提供了工厂的层级关系,可以使用它来获取父级工厂,本次呢,我们来学习SpringIOC中比较重要的一个接口,它是HierarchicalBeanFactory的子类,也就是ConfigurableBeanFactory。他的情况如下图所示:
刚看到这个接口的时候,头还是很大的,因为这个接口里的方法实在是太多了,多的令人发指,但鉴于他的重要性,所以决定出去吹个三九寒风,醒醒脑,然后继续研究.
ConfigurableBeanFactory是HierarchicalBeanFactory的子接口,同时它也继承了SingletonBeanRegistry.HierarchicalBeanFactory我们已经了解了,不再赘述.这里我们来看一下SingletonBeanRegistry,这个接口为容器中的单例Bean定义了一个注册表,一般来说BeanFactory的实现类都会实现这个接口,目的是使用一种统一的方式对外暴露他们的单例管理方式,我们来看一下他的api:
registerSingleton(String beanName,Object singletonObject):注册一个单例Bean.给定的那个Bean应该完全被初始化。这个注册器不会执行任何的初始化回调(尤其是,不会调用InitializingBean的afterPropertiesSet方法).给定的实例也不会收到任何的销毁性回调(比如DisposableBean的destroy方法).当一个满负荷的BeanFactory在运行的时候,如果你的Bean应该收到初始化或者销毁的回调,那么可以重新注册一个新的BeanDefinition来代替已存在的实例.比较典型地是在registry配置的时候调用这个函数,但也可以在registration运行的时候调用.因此,一个registry的实现无论他是否支持BeanFactory的单例懒加载,它都应该同步单例访问.
getSingleton(String beanName): 根据名字获取一个单例Bean.只检查已经被实例化的单例对象.如果一个单例BeanDefinitions还没有被实例化,它是不会被返回的.这个方法主要用于访问手动注册的单例Bean.也可以被用来访问一个使用BeanDefinition定义的已创建的单例Bean.需要注意的是,这个查询方法不会识别FactoryBean的前缀或别名.在获取单例实例之前,我们必须要确定一个靠谱点儿的Bean的名字.
containsSingleton(String beanName): 判断注册表是否包含指定名字的单例bean.与getSingleton(String beanName)一样,只检查已经被实例化的单例Bean,如果BeanDefinition还没有被实例化,是不会返回true的.这个方法主要用于检查手动注册的单例对象(registerSingleton),也可以用来检查一个使用BeanDefinition定义的单例是否被创建.为了检查BeanFactory是否包含一个给定名字的BeanDefinition,可以使用ListableBeanFactory的containsBeanDefinition.调用containsBeanDefinition和containsSingleton答复一个特定的BeanFactory是否包含一个指定名字的本地bean实例.使用BeanFactory的containsBean可以通用性地检查factory是否知道一个给定了名字的Bean(无论这个Bean是手动注册的,还是使用BeanDefinition创建的),并且这个方法也检查父级Factory.注意,这个查询方法也不会识别FactoryBean的前缀或别名.在检查单例状态之前,我们需要确定一个比较靠谱的Bean名字.
getSingletonNames(): 返回注册表中所有单例Bean的名字.只检查已经被实例化的单例,对于那些还没有被实例化的单例对象,它们的名字是不会被返回的.这个方法主要用来检查手动注册的单例.也可以用来检查使用BeanDefinition定义的已经被创建的单例对象.
getSingleCount(): 统计注册表中单例的个数,只检查已经被实例化的单例,对于还没有被实例化的单例则不会计算.这个方法主要用于检查手动注册的单例对象.也可以用来数算使用BeanDefinition定义的已经被创建的单例的数目.
getSingletonMutex(): 返回注册表中互斥的单例对象.4.2新增的一个接口.
通过以上的api,我们可以了解到,Spring对外提供了两种Bean的注册,第一种呢,是BeanDefinition这种类型的注册,这也是被普遍使用的,我们平时所使用的xml方式.而第二种呢,则是手动注册,刚刚我们看到的SingletonBeanRegistry主要就是服务于第二种***制.并且他们都只能获取到已被实例化的单例Bean,如果没有被实例化,则他们是无法被获取的.
现在我们来看一下ConfigurableBeanFactory.这是迄今为止,我们所见过的函数最多的一个BeanFactory.它会被大多数BeanFactory的实例实现。除了BeanFactory给beanFactory客户端提供的方法之外,它还提供了很多工具用来配置beanFactory.但是这个接口呢,并不打算被应用于正常的应用程序代码中,对于那些典型需要,请保持使用BeanFactory或ListableBeanFactory.这个扩展接口只是考虑到框架内部的即插即用以及BeanFactory配置方法的访问入口.我们现在来看一下这个接口的api:
1.首先是两个常量,一个是SCOPE_SINGLETON=”singleton”,另一个是SCOPE_PROTOTYPE=”prototype”.这两个是用来标明注册的对象作用域,一个标明注册的对象是单例的,另一个标明注册的对象是原型拷贝的.
2.其次呢,是setParentBeanFactory.这个函数是用来设置BeanFactory的父级.父级一旦被设定了,是不能改变的:如果在工厂实例化的时候父级还不能用,那么就要考虑在构造函数之外设置父级工厂.
3.然后是几组getter和setter:classLoader、tempClassLoader、cacheBeanMetadata、 beanExpressionResolver,conversionService、typeConverter、currentlyInCreation.
classLoader:主要用于加载Bean,默认是线程的上下文loader.这个classLoader只适用于还不确定bean class的BeanDefinition.而spring2.0默认的情况是:Bean Definition只携带bean class的名字,一旦factory开始处理BeanDefinition,这个BeanDefinition的class才会确定.并且只有当系统的classLoader也不可用时,getClassLoader才会返回Null.
tempClassLoader:为打成类型匹配而指定的临时性的ClassLoader.默认是无,直接使用标准的Bean ClassLoader.如果涉及到了LTW,一个tempClassLoader通常只是被指定用来确保真实的Bean尽可能地被懒加载.一旦BeanFactory完成了它的引导目标,这个tempClassLoader就会被移除.
cacheBeanMetadata:用来设置是否缓存给定BeanDefinition(以合并的方式)和确定类型Bean的元数据,默认是开启状态.关掉这个flag缓存可以启用beanDefinition对象尤其是确定类型的Bean的热刷新.如果这个flag是关掉状态,任何一个bean实例的创建操作都将重新查询bean class loader来确定这个Bean最新的类型.
beanExpressionResolver: 为beanDefinition值中的表达式提供解决策略.默认的BeanFactory里是没有**的表达式支持的.一个ApplicationContext通常会设置一个标准的表达式策略,以一种统一的EL兼容风格支持“#{}”表达式.
conversionService:指定一个Spring3.0 ConversionService来进行属性值的转换,是JavaBean中PropertyEditor的一种替代品.
typeConverter: 设置或获取自定义的类型转换器,BeanFactory用它来对Bean的属性值,构造参数等进行转换.这将会覆盖默认的PropertyEditor机制,因此,使用无关的自定义Editor或自定义Editor Registrars.因为TypeConverter通常不是线程安全的,所以每次调用都会产生一个新的实例.如果默认的PropertyEditor机制被**,获取typeConverter方法将会返回所有已被注册的自定义的typeConverter.
currentlyInCreation: 这一组函数只提供给内嵌的容器使用,用来精确地控制当前正处于创建过程中的指定Bean.isCurrentlyInCreation用来确定指定的Bean当前是否处于创建中.
4.接下来的是:PropertyEditor系列的函数:
addPropertyEditorRegistrar:添加一个PropertyEditorRegistrar应用于所有bean的创建过程.一个Registrar创建了一个新的PropertyEditor实例,并且会将他们注册到一个给定的Registry中,并尝试刷新每个bean的创建.这就避免了自定义Editor的同步应用需求.因此通常更倾向于使用这个方法来代替registerCustomEditor.
registerCustomEditor:为所有给定类型的属性注册一个给定的自定义属性编辑器.通常在factory配置期间被调用.注意这个方法注册一个共享的自定义属性编辑器实例;为了线程安全,需要授权该实例去进行同步操作.通常更倾向于使用addPropertyEditorRegistrar来代替这个方法,这就避免了自定义编辑器同步的需要.
copyRegisteredEditorsTo:使用一个已经在BeanFactory里注册过的自定义属性编辑器来初始化给定的PropertyEditorRegistry.
5.接着是一组嵌入式的值操作函数,可参考注解的属性获取:
addEmbeddedValueResolver用来增加一个嵌入式的StringValueResolver,比如说注解的属性.可以参考SpringMVC中的ArgumentResolver.
hasEmbeddedValueResolver,确定是否有一个嵌入式的value resolver已经在这个bean factory中注册了,并且可以通过resolveEmbeddedValue函数来应用.
resolveEmbeddedValue:解决一个给定的嵌入式的值,例如注解中的属性.
6.这里还有一组bean的后置处理器相关函数:
addBeanPostProcessor:添加一个新的BeanPostProcessor,通过这个工厂所创建的beans将会应用这个后置处理器.在工厂的配置期间调用.注意这里的Post-processor提交将会按着registration的顺序被依次应用.任何通过Ordered这个接口所实现的顺序语义将会被忽略.也要注意到自动检测的后置处理器将会在以编程方式注册的那些后置处理器之后执行.
getBeanPostProcessorCount:如果有的话,就返回当前已注册的BeanPostProcessor的数目.
7.之后是和Scope相关的一组函数:
registerScope:注册一个给定的scope,支持Scope的实现类.
getRegisteredScopeNames: 返回所有当前注册过的scope的名字.这个方法只返回明确注册过的scope的名字,内置的(Built-in)scopes像”singleton”和”prototype”不会被暴露.如果没有返回的是空数组.
getRegisteredScope(String scopeName): 如果有的话,返回给定名字的Scope实现.和上一个函数一样,将只返回明确注册过的scope,内置的(Built-in)scopes像”singleton”和”prototype”不会被暴露.
8.一些零散的功能性函数:
getAccessControlContext(): 提供一个与这个工厂相关的安全的访问控制上下文.这个绝不会为空.
copyConfigurationFrom(ConfigurableBeanFactory otherFactory):从给定的工厂中拷贝所有相关的配置信息.应该包括了所有标准的配置,也包括了BeanPostProcessor,Scopes和factory-specific内置的一些配置.应该不包括任何真实Bean的metadata信息,像BeanDefinition对象和bean的别名等.
registerAlias(String beanName,String ailas): 给定一个bean的名字,创建它的别名.这个方法的典型应用是支持那些在XML的ids里是无效的名字(被用于Bean的命名).通常都是在factory的配置期间被调用,但是也可以用于别名的registration的运行时.所以一个实现了该函数的接口应该同步别名访问.
resolveAliases: 处理所有目标名称的别名和在这个工厂注册过的别名,然后为它们应用给定的StringValueResolver.这个value resolver是处理像目标bean名称甚或在别名名称里的占位符而设置的.
getMergedBeanDefinition: 返回一个给定名字的合并后的BeanDefinition,如果有必要会将子BeanDefinition和父BeanDefinition进行合并.并且也会考虑祖先容器中的BeanDefinition.
isFactoryBean(String name): 判断给定名字的Bean是否是一个FactoryBean.
9.与Bean的生命周期相关的配置
registerDependentBean(String beanName,String dependentBeanName): 为给定名称的Bean注册一个依赖Bean,并且该依赖Bean会在给定的Bean被销毁之前进行销毁
getDependentBeans(String beanName): 如果有的话,返回依赖于给定名字Bean的所有Bean名称.
getDependenciesForBean(String beanName): 如果有的话,返回给定名字Bean所依赖的所有Bean名称.
destroyBean(String beanName,Object beanInstance): 依据BeanDefinition,销毁给定Bean的实例,(通常会从这个工厂中获取一个原型实例).在销毁期间所抛出的任何异常都应该用捕获来取代往这个方法的调用者那里抛出.
destroyScopeBean(String beanName): 如果有的话,在当前目标Scope中销毁指定的ScopeBean. 在销毁期间所抛出的任何异常都应该用捕获来取代往这个方法的调用者那里抛出.
destroySingletons(): 销毁这个工厂中所有的singleton bean,包括一次性的已经注册的内嵌Bean.在工厂关闭的时候会被调用. 在销毁期间所抛出的任何异常都应该用捕获来取代往这个方法的调用者那里抛出.
在看完ConfigurableBeanFactory后,我们会发现这个BeanFactory提供的接口大都是为BeanFactory的配置来服务的.这些配置信息,我们会在一些较高层的BeanFactory实现中会经常看到.
现在我们距离一个真实可用的BeanFactory实现已经越来越近了,我们将会在下一次分享ConfigurableListableBeanFactory,在那里我们会接触一些更为实用的一些函数声明.如果有什么好的建议或者指正,欢迎大家留言或者发邮件([email protected])给我.