Spring之BeanFactory

BeanFactory

继承体系

defaultListableBeanFactoryUML.png

我们先从继承体系的左半部分开始看。

BeanFactory接口:

BeanFactory是用于访问Spring容器的根接口,他是最基本的客户端视图(basic client view of a bean container)。一般情况下BeanFactory的实现类都持有一组bean的定义(彼此之间通过唯一的name区分),根据bean的定义,beanFactory中一系列重载的getBean()方法可以根据参数获取bean实例。因此,BeanFactory是应用程序组件的中央注册表,并且集中管理应用程序组件的相关配置信息。此外,BeanFactory的实现类应该尽可能的支持标准的Bean生命周期接口,他们的初始化顺序是:
  1. BeanNameAware的 setBeanName
  2. BeanClassLoaderAware的 setBeanClassLoader
  3. BeanFactoryAware的 setBeanFactory
  4. EnvironmentAware的 setEnvironment
  5. EmbeddedValueResolverAware的 setEmbeddedValueResolver
  6. ResourceLoaderAware的 setResourceLoader
  7. ApplicationEventPublisherAware 的 setApplicationEventPublisher
  8. MessageSourceAware的 setMessageSource
  9. ApplicationContextAware的 setApplicationContext
  10. ServletContextAware的 setServletContext
  11. BeanPostProcessors的 postProcessBeforeInitialization 方法
  12. InitializingBean的 afterPropertiesSet
  13. 自定义初始化方法init-method
  14. BeanPostProcessors的postProcessAfterInitialization方法
  其中,6、7、8、9、10 仅在应用程序上下文[ApplicationContext]中运行时适用。

关闭BeanFactory时的生命周期方法:

  1. postProcessBeforeDestruction DestructionAwareBeanPostProcessors的方法
  2. DisposableBean的的 destroy
  3. 自定义销毁方法destory-method

HierarchicalBeanFactory

父子级联的IOC容器接口,子容器可以通过方法访问父容器,从而获取父容器内的相关信息。

ListableBeanFactory

继承BeanFactory,提供了更多的访问Bean及其相关信息的方式。相比BeanFactory大部分只能通过getBean()获取bean实例,ListableBeanFactory接口定义了通过指定类型获取Bean实例、通过指定相关注解信息获取Bean实例以及查看容器中有多少bean定义、检索容器中所有bean的名称等。方法举例:

注意:假设一个BeanFactory 既实现了ListableBeanFactory 又实现了HierarchcalBeanFactory,那么所有ListableBeanFactory 接口方法实现都会忽略BeanFactory的继承层次,只返回当前BeanFactory容器中的信息。

AutowireCapableBeanFactory

继承BeanFactory,使容器具有为Bean实例的属性进行自动装配的能力。其他框架可以使用此接口的功能填充那些生命周期不是Spring容器管理的Bean,比如Struts的Action实例.在应用程序上下文中,可以使用`[ApplicationContext.getAutowireCapableBeanFactory()](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/ApplicationContext.html#getAutowireCapableBeanFactory--)`获取。也可以通过实现`[BeanFactoryAware](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/BeanFactoryAware.html)`来使bean具有获取AutowireCapableBeanFactory的能力。AutowireCapableBeanFactory在应用程序中一般尽量避免使用,使用BeanFactory与ListableBeanFactory更明智些。该接口定义的方法主要有如下三种:
  1. Typical methods for creating and populating external bean instances(创建和填充外部Bean实例的方法)
    		2. Specialized methods for fine-grained control over the bean lifecycle(细粒度的控制Bean的生命周期方法)

  	3. Delegate methods for resolving injection points(解析注入点的代理方法)

ConfigurableBeanFactory

该接口继承了HierarchicalBeanFactory接口与SingletonBeanRegistry接口(后文介绍),为容器提供了可定制化的方法,比如:设置父容器、设置容器的默认BeanClassLoader、设置类型转换器、添加属性编辑器(PropertyEditor)和BeanPostProcessor等一系列的定制方法。

SingletonBeanRegistry

单例Bean注册表,定义了一组向容器注册及检索单例Bean相关信息的方法。定义该接口的目的是为BeanFactory的实现类(也就是容器)提供一组管理单例Bean的统一方法,作为容器的基础设施。

ConfigurableListableBeanFactory

[Spring官方文档](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/config/ConfigurableListableBeanFactory.html)给该接口的定义是一个Configuration interface(配置接口)。大多数的listable的BeanFactory都可以实现它。它除了继承 ConfigurableBeanFactory中的配置方法以外,还添加了访问和修改Bean的定义、预实例化单例等功能。此接口也不建议在应用程序中直接使用。此接口的设计目的是为了满足Spring框架内部的即插即用(plug'n'play)。

下面看体系结构的右半部分

AliasRegistry

Alias的注册管理接口,定义了Alias的增删改查操作。

BeanDefinitionRegistry

容纳Bean定义的注册器,定义了BeanDefinition的增删改查方法。BeanDefinitionRegistry的实现类一般会持有一系列的BeanDeifinition实例,比如:RootBeanDefinition和ChildBeanDefinition 等,因此一般的BeanFactory实现类也会实现该接口。Spring内部的BeanDefinitionReader可以与该接口的实现类协同工作,读取并注册BeanDefinition.值得一提的是,DefaultListableBeanFactory和GenericApplicationContext均实现了该接口。

SimpleAliasRegistry

使用ConcurrentHashMap作为缓存对AliasRegistry接口进行实现。值得一提的是:这个简单实现很多方法是递归的。举例:A的别名是B,B的别名是C,那么显然别名具有传递性,C也成了A的别名。

DefaultSingletonBeanRegistry

SingletonBeanRegistry的默认实现,其内部使用map缓存Bean实例。同时它也继承了SimpleAliasRegistry,说明他继承了别名管理的能力。此外,它还支持DisposableBean实例的注册,在Registry(注册表)关闭时可以调用其distory()方法。这个类可以作为一个实现BeanFactory功能的实现基类来使用。

FactoryBeanRegistrySupport

在DefaultSingletonBeanRegistry的基础上添加了对FactoryBean注册的支持,AbstractBeanFactory的基类。

AbstractBeanFactory

集成了DefaultSingletonBeanRegistry与ConfigurableBeanFactory的能力,作为一个抽象类,他有三个方法希望子类去实现:

/**
 * Check if this bean factory contains a bean definition with the given name.
 * Does not consider any hierarchy this factory may participate in.
 * Invoked by {@code containsBean} when no cached singleton instance is found.
 * <p>Depending on the nature of the concrete bean factory implementation,
 * this operation might be expensive (for example, because of directory lookups
 * in external registries). However, for listable bean factories, this usually
 * just amounts to a local hash lookup: The operation is therefore part of the
 * public interface there. The same implementation can serve for both this
 * template method and the public interface method in that case.
 * @param beanName the name of the bean to look for
 * @return if this bean factory contains a bean definition with the given name
 * @see #containsBean
 * @see org.springframework.beans.factory.ListableBeanFactory#containsBeanDefinition
 */
protected abstract boolean containsBeanDefinition(String beanName);

/**
 * Return the bean definition for the given bean name.
 * Subclasses should normally implement caching, as this method is invoked
 * by this class every time bean definition metadata is needed.
 * <p>Depending on the nature of the concrete bean factory implementation,
 * this operation might be expensive (for example, because of directory lookups
 * in external registries). However, for listable bean factories, this usually
 * just amounts to a local hash lookup: The operation is therefore part of the
 * public interface there. The same implementation can serve for both this
 * template method and the public interface method in that case.
 * @param beanName the name of the bean to find a definition for
 * @return the BeanDefinition for this prototype name (never {@code null})
 * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
 * if the bean definition cannot be resolved
 * @throws BeansException in case of errors
 * @see RootBeanDefinition
 * @see ChildBeanDefinition
 * @see org.springframework.beans.factory.config.ConfigurableListableBeanFactory#getBeanDefinition
 */
protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;

/**
 * Create a bean instance for the given merged bean definition (and arguments).
 * The bean definition will already have been merged with the parent definition
 * in case of a child definition.
 * <p>All bean retrieval methods delegate to this method for actual bean creation.
 * @param beanName the name of the bean
 * @param mbd the merged bean definition for the bean
 * @param args explicit arguments to use for constructor or factory method invocation
 * @return a new instance of the bean
 * @throws BeanCreationException if the bean could not be created
 */
protected abstract Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException;

AbstractAutowireCapableBeanFactory

AbstractBeanFactory的基础上实现了Bean的自动装配功能,继承了AbstractBeanFactory的功能(bean的注册,查找等)。

DefaultListableBeanFactory

实现了整个继承体系中的所有功能。通过实现ConfigurableListableBeanFactory获得Bean的增删改查及factory容器的定制功能,通过实现BeanDefinitionRegistry获得BeanDefinition的增删改查功能。典型使用方式是:先注册所有的BeanDefinition(一般通过注解扫描或者xml读取),再访问BeanDefinition创建Bean.

Spring框架中IOC容器包含在 org.springframework.beans 和org.springframework.context两个基本包中。BeanFactory提供配置和管理Bean对象的基本方法,ApplicationContext在此基础上添加了如下特性:

● 方便集成Spring AOP特性
● 处理MessageResource(国际化使用)
● 事件发布
● 面向特定应用场景的上下文(如:web应用使用的WebApplicationContext)

总之,BeanFactory提供的是Spring框架使用的基本功能,而ApplicationContext则提供更多的面向企业开发的功能特性。在Spring框架中, org.springframework.context.ApplicationContext 接口表示 Spring IoC 容器并负责配置、初始化及装配Bean。

Spring框架提供了ApplicationContext 接口的若干实现如:AnnotationConfigApplicationContext、FileSystemXmlApplicationContext和ClassPathXmlApplicationContext。

● AnnotationConfigApplicationContext使用注解作为配置元数据来初始化容器
● FileSystemXmlApplicationContext从文件系统中加载xml文件来作为配置元数据
● ClassPathXmlApplicationContext从类路径中加载xml文件作为配置元数据

Spring参考博客

posted @ 2023-01-31 14:39  小张同学哈  阅读(53)  评论(0)    收藏  举报