BeanFactory 顶层接口源码阅读

一 API 阅读

获取一个 SpringBean 容器的根接口。是客户端的基础 bean 视图;还有一些其他的接口比如

ListableBeanFactory
org.springframework.beans.factory.config.ConfigurableBeanFactory

是为一些特殊的目的而编写的。

这个接口由那些持有一定量 bean 定义(bean definition) 的对象实现,这些 bean 由字符串做唯一标识。根据 bean 定义,工厂会返回一个独立的实例,或者一个单独的共享实例(一种相较于单例设计模式的更好的选择,得到一个在工厂作用域范围内的单例实例)。返回实例的类型取决于 bean 工厂的配置:API是相同的。从 Spring2.0 开始,更多可选的 bean 作用域都由不同的上下文实现了(比如 request 和 session 作用域)。

这种设计方案的 核心 要点是 BeanFactory 会成为应用程序组件的注册中心,由此集中化应用程序的组件配置信息。

相比于 beanFactory 查找 bean 配置信息的方式,依靠依赖注入,使用 setter 和 constructor 来配置应用的对象是更好的方案。Spring的依赖注入功能正是通过实现BeanFactory和其子接口实现的。

正常情况下 beanFactory 会加载保存于一些配置源的 bean 配置信息(这些配置源可以是 XML/properties配置文件等等),并使用 ==org.springframework.beans== 包下的工具来配置这些 bean。不过 beanFactory 的实现类可以简单的通过 Java 代码直接创建 bean 实例并返回。这里也没有限制 bean 定义信息的保存载体:LDAP/RDBMS/XML 或者 properties 文件等等。beanFactory 的实现类更鼓励支持引用而不是依赖注入的bean(?)。

beanFactory 的实现类应该尽可能地支持 bean 的生命周期接口。完整的初始化方法和它们的初始化顺序是:

  • BeanNameAware's {@code setBeanName}
  • BeanClassLoaderAware's {@code setBeanClassLoader}
  • BeanFactoryAware's {@code setBeanFactory}
  • EnvironmentAware's {@code setEnvironment}
  • EmbeddedValueResolverAware's {@code setEmbeddedValueResolver}
  • ResourceLoaderAware's {@code setResourceLoader}(only applicable when running in an application context)
  • ApplicationEventPublisherAware's {@code setApplicationEventPublisher} (only applicable when running in an application context)
  • MessageSourceAware's {@code setMessageSource}(only applicable when running in an application context)
  • ApplicationContextAware's {@code setApplicationContext} (only applicable when running in an application context)
  • ServletContextAware's {@code setServletContext} (only applicable when running in a web application context)
  • {@code postProcessBeforeInitialization} methods of BeanPostProcessors
  • InitializingBean's {@code afterPropertiesSet}
  • a custom init-method definition
  • {@code postProcessAfterInitialization} methods of BeanPostProcessors

二 类成员与接口定义的方法

String FACTORY_BEAN_PREFIX = "&";

用于 间接引用 一个 FactoryBean,以及区分 FactoryBean 和 FactoryBean 创建的实例。比如,myJndiObject 是一个 factoryBean,那么使用 name = "&myJndiObject",得到的是 factory,而不是 factory 中保存的 bean 实例。

Object getBean(String name) throws BeansException;

工厂接口中的基础核心方法定义,当容器已经启动完成,我们需要使用这个方法的实现,来获取对应的 bean 实例。获取到的 bean,具体是单例还是其他类型的,取决于提前定义好的 bean 信息(即 beanDefination)。

 T getBean(String name, Class requiredType) throws BeansException;

这个方法和前一个方法很类似,区别在于参数列表上多了一个 class 类型信息。相较于前面的一个方法,该方法对要获取的 bean 实例的限制信息更加明确,这样可以 避免类型转换异常。

 T getBean(Class requiredType) throws BeansException;

依据传入的类型参数信息来获取 bean 的实例。这个方法没有要求传入 bean 的名称。实际上其实是一个很模糊的范围检索的 bean 获取方式。

Object getBean(String name, Object... args) throws BeansException;

获取指定 beanName 的 bean 实例,添加了一个可变参数列表,这个可变参数列表用于传入创建对应 bean 所需的 构造方法或者工厂方法 的参数。这个方法的应用,我们可以联想到在 xml 里面配置 bean 信息的时候,要求指定这个 bean 初始化是使用工厂方法还是构造函数的时候。

如上是 getBean 一系列的重载方法。

boolean containsBean(String name);

用户检索当前 beanFactory 是否包含指定的 bean。这个包含的含义,可以是 bean definition,也可以是执行 beanName 的单例实例。如果传入的 name 是别名,那将会被转换为标准的 bean 名称。

部分继承结构的 beanFactory ,在调用这个方法的时候也会查询父类容器中是否包含了指定 beanName 的对象实例。

注意只要在 factory 中发现了对应的 bean definition 或者单例的实例。不管这个 bean 是否已经被实例化,抑或是处于为被加载的 延迟加载 状态,都会返回 true。

因此我们要注意到,不是说 containsBean 方法返回了 true,使用 getBean 方法就一定会拿到对应的 bean 实例。

boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

该方法用于判断指定的 bean 是否是 单例。当判断的方法返回了 true。当然可以说明这个 bean 是一个单例 bean。但是当方法的返回值是 false 的时候,并不意味着这个 bean 是一个 prototype 类型的 bean(应用:原型设计模式)。如果要判断 bean 的作用域是否是 prototype,可以使用另一个方法 isPrototype。

boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

该方法用于判断指定的 bean 是否是 原型设计模式下的实例(prototype)。与前一个方法类似,返回 true 表示这个 bean 的作用域一定是 prototype,但是返回 false 并不意味着这个 bean 是一个单例实例。

boolean isTypeMatch(String name, Class typeToMatch) throws NoSuchBeanDefinitionException;

用于对想要获取的 bean 的类型检查。

Class getType(String name) throws NoSuchBeanDefinitionException;

获取指定 bean 的类型信息。

String[] getAliases(String name);

获取指定 bean 的别名数组。

三 ListableBeanFactory

3.1 API 文档简述

一个实现了 BeanFactory 的扩展接口,用户枚举工厂中的所有 bean 实例,而不是通过客户端请求,用名字挨个获取。 需要预先加载 beanFactory 中所有的 beanDefinition 的工厂类会考虑实现这个扩展接口。

如果实现了该接口的类还实现了 HierarchicalBeanFactory,那么方法的返回值将不会考虑父容器中定义的 bean,而仅关注于当前的 beanFactory 中的 bean。如果有必要,可以使用 BeanFactoryUtils 中的方法来获取父类容器中的 bean。

这个接口中的方法也仅仅考虑当前 beanFactory 中的 beanDefinition。类似于 ConfigurableBeanFactory.registerSingleton 这种注册单例 bean 的方法会在当前接口方法中被忽略。例外的是 getBeanNamesOfType 和 getBeansOfType 这样的方法会考虑注册的单例。

当前接口中的部分方法不是为了快速响应而设计。 getBeanDefinitionCount 和 containsBeanDefinition 性能比较低下。少用为好。

3.2 方法描述

boolean containsBeanDefinition(String beanName);

检查当前容器是否包含执行 beanName 的 beanDefinition 信息。不会检索父容器的内容,同时还会忽略任何使用非 definition 方式注册的单例 bean。

int getBeanDefinitionCount();

返回当前 bean 容器定义的 bean 数量。不会记入父容器中的 bean 数量。忽略使用非 bean definition 方式注册的 bean。

String[] getBeanDefinitionNames();

返回当前容器中定义的所有的 bean 的 beanName,得到一个字符串数组。不会记入父容器中的 bean 数量。忽略使用非 bean definition 方式注册的 bean。

String[] getBeanNamesForType(ResolvableType type);

根据 bean 的类型信息来获取指定类型信息的 beanName 数组。判断的依据是:容器中是否存在对应的 beanDefinition 或者 getObjectType方法返回有效的实例信息

String[] getBeanNamesForType(Class type);

系列方法的重载。入参类型不同,前者是 Spring 自定义的一种类型辅助类。

String[] getBeanNamesForType(Class type, boolean includeNonSingletons, boolean allowEagerInit);

多出了两个参数,对对应 beanName 的获取有更加明确的限定条件。

  • boolean includeNonSingletons 是否限定仅获取单例类型 bean 的 beanName
  • boolean allowEagerInit 是否将“延迟加载”的 bean 实例化。
 Map getBeansOfType(Class type) throws BeansException;

根据 class 对象类型来获取 bean 的实例集合。结果都保存在一个 map 中。这个指定的类型,可以是类本身类型也可以是其子类对象类型。不会忽略以非 beanDefinitions 方式初始化的单例 bean。也不会检索父容器中的 bean。

     Map getBeansOfType(Class type, boolean includeNonSingletons, boolean allowEagerInit)
        throws BeansException;

上一个方法的重载,新的入参含义和前面的方法类似。

    String[] getBeanNamesForAnnotation(Class annotationType);

然后是一系列根据 bean 代码中添加的注解类型来获取 beanName/bean集合 的方法。

String[] getBeanNamesForAnnotation(Class annotationType);

Map getBeansWithAnnotation(Class annotationType) throws BeansException;

...

四 HierarchicalBeanFactory

4.1 API

beanFactory 的扩展子接口,可以作为容器层级中的一部分。

与这个层级扩展接口相比,还有对应的 setParentBeanFactory 方法,这个方法需要另一个同级的扩展接口 ConfigurableBeanFactory

接口中定义的方法也很少,只有两个

BeanFactory getParentBeanFactory();

返回当前容器的父容器

boolean containsLocalBean(String name);

判断当前容器是否包含指定了 beanName 的bean,不会检索父容器中的 bean。这个方法可以和 containsBean 方法结合对比:

基类接口中的 containsBean 方法,是否检索父类容器的 bean 也要视情况而定。文档中清晰的说明了:如果是处于一个包含层级容器结构的 beanFactory 中,那么这个方法是会去检索父类容器的。但是 containsLocalBean 就是明确指出了不会检索父容器。

五 AutowireCapableBeanFactory

beanFactory 的扩展接口。这个扩展接口主要定义了关于 bean 的自动装配部分的内容。

这个扩展接口也不是用户常规的应用代码,常常与 BeanFactory 或者 ListableBeanFactory 搭配使用。

其他框架可以集成这个接口代码以操控 Spring 中已经存在的且无法控制其生命周期的 bean 实例。

这个接口也没有被 ApplicationContext 实现,虽然这个接口也曾用于上下文的代码。获取方法见 ApplicationContext.getAutowireCapableBeanFactory()

5.1 类成员

int AUTOWIRE_NO = 0;

用于指示没有外部定义的自动装配信息的常量。诸如 BeanFactoryAware 等注解驱动的注入依然是有效的。

int AUTOWIRE_BY_NAME = 1;

用于指明根据 name 自动装配 bean 属性的常量。

int AUTOWIRE_BY_TYPE = 2;

用于指明根据类型 自动装配 bean 属性的常量。

int AUTOWIRE_CONSTRUCTOR = 3;

用于指明根据合适的构造函数 自动装配 bean 属性的常量。

5.2 方法定义

 T createBean(Class beanClass) throws BeansException;

创建给定类的全新的实例。会执行完整的 bean 实例化逻辑。包含可用的 bean 预处理方法,比如 BeanPostProcessor。

该方法不是传统的 按名字 或者 按类型 的自动装配,如果要达到这一目的,可以使用另一个方法 createBean(Class, int, boolean)

void autowireBean(Object existingBean) throws BeansException;

该方法名就可以简要了解到方法的用途:自动装配 bean。在一些 bean 的初始化工作完成后,这些 bean 中的一部分采用了组装的技巧耦合的其他的 bean。这个时候我们需要把这些由 spring 托管的 bean 的实例装配到对应的地方。

这个自动装配方法在 bean 的实例化过程中的, after-instantiation 以及 属性初始化中的 post=processing 的阶段执行。注解驱动的 bean 注入就是依赖了这个方法定义。

这个方法本质上就是装配注解的类成员和方法,或者说是反序列化 bean 实例。和前一个方法一样,该方法也不是传统的 按名字 或者 按类型 装配。

Object configureBean(Object existingBean, String beanName) throws BeansException;

配置一个(接近完成的) bean:装配 bean 的域,初始化域的值和相关的回调函数(比如 set/get 和 xml 中配置的工厂方法)。

该方法是 initializeBean 的方法超集。会完整执行对应的 beanDefinition 实例中配置的信息。需要注意的是该方法需要对应 beanDefinition 的名字。

有关 bean 生命周期控制的详细方法列表

Object createBean(Class beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
Object autowire(Class beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck)
        throws BeansException;
...

这些系列方法,基本上都是 bean 的初始化,bean 的自动装配,bean 的属性值获取等等,很多初始化策略都已经在接口中以常量的方式定义了。比如 是按类型装配还是按名字装配。

除了的 bean 的初始化,还有几个关于 bean 创建完成后的处理方法(postProcessing)已经销毁已经创建的 bean 的方法(destroy bean)。

=====

 NamedBeanHolder resolveNamedBean(Class requiredType) throws BeansException;

解析出符合类型要求的 bean。

Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName) throws BeansException;

解析出指定 beanName 的依赖 bean。

Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName,
        Set autowiredBeanNames, TypeConverter typeConverter) throws BeansException;

同上,差异在入参。

六 简要总结

BeanFactory 接口是 Spring 中有关 bean 管理的顶级接口,然后其下的三个扩展接口又对这个顶层接口做了不同程度的扩展。各个扩展接口的目的和方向也各不相同。

ListableBeanFactory 可以通过遍历获取 factory 中的所有 bean 实例。也包含了一些有关 bean 数量统计的方法。

HierarchicalBeanFactory 是一个层级扩展接口,有关父子容器关系的定义内容。方法很少,就一个 获取父容器判断是否包含父容器。 当我们需要使用有层级关系的 beanFactory 时,需要实现这个接口。

AutowireCapableBeanFactory 是处理有关 bean 容器中的 bean 自动装配操作的扩展接口。接口中定义了一些列的方法,用于 解析和装配有依赖关系的 bean控制 bean 的完整的生命周期

你可能感兴趣的:(BeanFactory 顶层接口源码阅读)