Spring之BeanFactory
BeanFactory
继承体系

我们先从继承体系的左半部分开始看。
BeanFactory接口:
BeanFactory是用于访问Spring容器的根接口,他是最基本的客户端视图(basic client view of a bean container)。一般情况下BeanFactory的实现类都持有一组bean的定义(彼此之间通过唯一的name区分),根据bean的定义,beanFactory中一系列重载的getBean()方法可以根据参数获取bean实例。因此,BeanFactory是应用程序组件的中央注册表,并且集中管理应用程序组件的相关配置信息。此外,BeanFactory的实现类应该尽可能的支持标准的Bean生命周期接口,他们的初始化顺序是:
- BeanNameAware的
setBeanName - BeanClassLoaderAware的
setBeanClassLoader - BeanFactoryAware的
setBeanFactory - EnvironmentAware的
setEnvironment - EmbeddedValueResolverAware的
setEmbeddedValueResolver - ResourceLoaderAware的
setResourceLoader - ApplicationEventPublisherAware 的
setApplicationEventPublisher - MessageSourceAware的
setMessageSource - ApplicationContextAware的
setApplicationContext - ServletContextAware的
setServletContext - BeanPostProcessors的
postProcessBeforeInitialization方法 - InitializingBean的
afterPropertiesSet - 自定义初始化方法init-method
- BeanPostProcessors的
postProcessAfterInitialization方法
其中,6、7、8、9、10 仅在应用程序上下文[ApplicationContext]中运行时适用。
关闭BeanFactory时的生命周期方法:
postProcessBeforeDestructionDestructionAwareBeanPostProcessors的方法- DisposableBean的的
destroy - 自定义销毁方法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更明智些。该接口定义的方法主要有如下三种:
- 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文件作为配置元数据
浙公网安备 33010602011771号