Spring源码分析带你正视一下Spring祖容器之BeanFactory的原理与功能分析

少年辛苦终身事,莫向光阴惰寸功。这篇文章主要讲述Spring源码分析带你正视一下Spring祖容器之BeanFactory的原理与功能分析相关的知识,希望能为你提供帮助。
BeanFactory
BeanFactory类的介绍
BeanFactory里注释进行详细分析.
BeanFactory的介绍说明

  • 访问一个Spring bean容器的根接口。这是一个bean容器的基本客户端视图;
    进一步的接口,如 ListableBeanFactory 和org.springframework.beans.factory.config.ConfigurableBeanFactory}可用于特殊目的。
BeanFactory的作用范围
  • 【Spring源码分析带你正视一下Spring祖容器之BeanFactory的原理与功能分析】此接口由持有一些bean定义的对象来实现,每个bean由String字符串唯一标识。根据bean定义,工厂将返回一个独立对象实例(原型设计模式),或者一个单个共享实例(Singleton设计模式的优雅代替实现,其中该实例是一个factory范围内的单例)。
  • 实例的哪种类型将被返回依赖于bean工厂配置:即使API是一样的。从Spring2.0开始,作用域扩展到根据具体的应用上下文,如web环境的request,session。
BeanFactory的作用职能
  • 这种方案的关键是,BeanFactory的是应用程序组件注册的中心,同时集中应用程序组件的配置(程序模块不再需要读取诸如properties的配置文件)。这种设计的更多好处讨论详见的< J2EE设计开发编程指南> 第4和第11章.
  • 相比诸如 BeanFactory 中查找的pull配置方式,通过setters或者构造方法,依赖注入的方式配置应用对象更好,Spring的依赖注入功能就是通过实现BeanFactory和其子接口实现的.
  • 通常,一个BeanFactory会从配置源(如XML文件)中加载bean对象模型,并使用{@code org.springframework.beans}包解析bean。然而,实现可以简单地返回java代码直接新建的Java对象。这里没有限制bean 定义文件的格式:LDAP,RDBMS,XML.实现类欢迎支持应用而非bean(依赖注入)
  • 对比{@ListableBeanFactory}中的方法,如果这是一个{@link HierarchicalBeanFactory},这个接口的全部实现都会查找父工厂,如果在这个工厂实例找不到bean,去直接父工厂查找。factory实例中的bean会覆盖父factory实例中的同名bean。
  • 实现类应该尽量支持标准bean的生命周期接口.全套的初始化方法。
public interface BeanFactory {/** * 用于区分是否直接获取FactoryBean实例. * bean以& 开头表示获取FactoryBean实例.否则获取created的实例.For example, if the bean named * {@code myJndiObject} is a FactoryBean, getting {@code & myJndiObject} * will return the factory, not the instance returned by the factory. */ String FACTORY_BEAN_PREFIX = "& "; /** * 返回一个原型或者单例实例. * 抢单例,原型设计模式的饭碗 * 可以根据别名查找,也可以去父容器实例查找 */ Object getBean(String name) throws BeansException; /** * 加个类型 */ < T> T getBean(String name, Class< T> requiredType) throws BeansException; /** * 根据类型获取bean实例.可以是接口或子类,但不能是{@code null}. * {@link ListableBeanFactory}也可以使用类型转化为name进行查找.更多bean集合的操作可以看 * ListableBeanFactory和BeanFactoryUtils */ < T> T getBean(Class< T> requiredType) throws BeansException; /** * 多了构造方法,工厂方法的参数 */ Object getBean(String name, Object... args) throws BeansException; /** * 判断是否包含bean(包括别名,父容器) * 陷阱出现:这边不管类是否抽象类,懒加载,是否在容器范围内,只要符合都返回true,所以这边true,不一定能从getBean获取实例 */ boolean containsBean(String name); /** * 是否单例 */ boolean isSingleton(String name) throws NoSuchBeanDefinitionException; /** * 是否原型 */ boolean isPrototype(String name) throws NoSuchBeanDefinitionException; /** * 是否有跟name匹配类型的bean */ boolean isTypeMatch(String name, Class< ?> targetType) throws NoSuchBeanDefinitionException; /** * 根据bean name获取类型 */ Class< ?> getType(String name) throws NoSuchBeanDefinitionException; /** * 获取别名 */ String[] getAliases(String name); }

  • Object getBean(String name) throws BeansException; 可以用别名查找哦
  • < T> T getBean(String name, Class< T> requiredType) throws BeansException;
  • < T> T getBean(Class< T> requiredType) throws BeansException; 这边的类型可以是接口或者子类,但不能是null
  • Object getBean(String name, Object... args) throws BeansException;
  • 判断是否包含bean.陷阱出现:这边不管类是否抽象类,懒加载,是否在容器范围内,只要符合都返回true,所以这边true,不一定能从getBean获取实例
    • boolean containsBean(String name);
  • 单例,原型,bean类型的判断
    • boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
 - boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
 - boolean isTypeMatch(String name, Class< ?> targetType) throws
NoSuchBeanDefinitionException;
  • 获取bean 的类型,别名
     
    • Class< ?> getType(String name) throws NoSuchBeanDefinitionException;
    • String[] getAliases(String name);
BeanFactory的架构模型机制
  • AutowireCapableBeanFactory 添加集成其他框架功能,如果集成WebWork则可以使用Spring对Actions等进行管理.
    • HierarchicalBeanFactory:提供父容器的访问功能
    • ConfigurableBeanFactory:如名,提供factory的配置功能。
      • ConfigurableListableBeanFactory:集大成者,提供解析,修改bean定义,并与初始化单例.
  • ListableBeanFactory 提供容器内bean实例的枚举功能,这边不会考虑父容器内的实例.
Spring源码分析带你正视一下Spring祖容器之BeanFactory的原理与功能分析

文章图片

AutowireCapableBeanFactory在BeanFactory基础上实现对已存在实例的管理.
  • 可以使用这个接口集成其它框架,捆绑并填充并不由Spring管理生命周期并已存在的实例.像集成其他框架机制。
  • 一般应用开发者不会使用这个接口,所以像ApplicationContext这样的外观实现类不会实现这个接口,如果真手痒痒可以通过ApplicationContext的getAutowireCapableBeanFactory接口获取。
这边定义了5种自动装配策略:
  • 不注入:AUTOWIRE_NO
  • 使用bean name策略装配:AUTOWIRE_BY_NAME
  • 使用类型装配策略:AUTOWIRE_BY_TYPE
  • 使用构造器装配策略:AUTOWIRE_CONSTRUCTOR
  • 自动装配策略:AUTOWIRE_AUTODETECT
这边的自动策略是先尝试构造器,然后才是byType,应该是跟xml配置文件中的装配策略对应。
创建和填充外部bean实例的典型方法
< T> T createBean(Class< T> beanClass) throws BeansException; // 使用autowireBeanProperties装配属性 void autowireBean(Object existingBean) throws BeansException; // 自动装配属性,填充属性值,使用诸如setBeanName,setBeanFactory这样的工厂回调填充属性,最好还要调用post processor Object configureBean(Object existingBean, String beanName) throws BeansException; Object resolveDependency(DependencyDescriptor descriptor, String beanName) throws BeansException;

在bean的生命周期进行细粒度控制的专门方法
Object createBean(Class< ?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException; // 会执行bean完整的初始化,包括BeanPostProcessors和initializeBeanObject autowire(Class< ?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException; void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck) throws BeansException; void applyBeanPropertyValues(Object existingBean, String beanName) throws BeansException; Object initializeBean(Object existingBean, String beanName) throws BeansException; Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException; Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException; Object resolveDependency(DependencyDescriptor descriptor, String beanName, Set< String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException;

HierarchicalBeanFactory获取父容器 bean factory判断当前容器是否保护beanListableBeanFactory获取bean时,Spring 鼓励使用这个接口定义的api,其他的4个接口都是不鼓励使用的.
提供容器中bean迭代的功能,不再需要一个个bean地查找,比如可以一次获取全部的bean,根据类型获取bean.在看SpringMVC时,扫描包路径下的具体实现策略就是使用的这种方式(那边使用的是BeanFactoryUtils封装的api).
如果同时实现了HierarchicalBeanFactory,返回值不会考虑父类BeanFactory,只考虑当前factory定义的类.当然也可以使用BeanFactoryUtils辅助类来查找祖先工厂中的类.
  • 这个接口中的方法只会考虑本factory定义的bean.
  • 这些方法会忽略ConfigurableBeanFactory的registerSingleton注册的单例bean(getBeanNamesOfType和getBeansOfType是例外,一样会考虑手动注册的单例).
  • 当然BeanFactory的getBean一样可以透明访问这些特殊bean.当然在典型情况下,所有的bean都是由external bean定义,所以应用不需要顾虑这些差别.
暴力获取全部bean的属性:
  • boolean containsBeanDefinition(String beanName); //是否包含bean
  • int getBeanDefinitionCount();  // 当前factory中定义的bean数量
  • String[] getBeanDefinitionNames(); // 获取当前工厂中定义的所有bean 的name
根据bean的类型获取bean
这边的方法仅检查顶级bean.它不会检查嵌套的bean.FactoryBean创建的bean会匹配为FactoryBean而不是原始类型.
一样不会考虑父factory中的bean,非要用可以通过BeanFactoryUtils中的beanNamesForTypeIncludingAncestors.
这个版本的getBeanNamesForType会匹配所有类型的bean,包括单例,原型,FactoryBean.返回的bean names会根据backend 配置的进行排序.
  • String[] getBeanNamesForType(Class< ?> type); // 获取给定类型的bean names(包括子类),通过bean 定义或者FactoryBean的getObjectType判断.
  • String[] getBeanNamesForType(Class< ?> type, boolean includeNonSingletons, boolean allowEagerInit);
  • < T> Map< String, T> getBeansOfType(Class< T> type) throws BeansException; // 如果保护懒加载的类,FactoryBean初始化的类和工厂方法初始化的类会被初始化.就是说执行这个方法会执行对应的初始化.
  • < T> Map< String, T> getBeansOfType(Class< T> type, boolean includeNonSingletons, boolean allowEagerInit) throws BeansException;
查找使用注解的类
  • Map< String, Object> getBeansWithAnnotation(Class< ? extends Annotation> annotationType) throws BeansException;
查找一个类上的注解,如果找不到,父类,接口使用注解也算.
  • < A extends Annotation> A findAnnotationOnBean(String beanName, Class< A> annotationType);

    推荐阅读