前言
前面的对象创建的整体流程我们已经学完了,那么接下来我们该学一学高级工厂ApplicationContext的用法了。
Spring的核心容器DefaultListableBeanFactory类
spring的核心容器:DefaultListableBeanFactory。
类图:
继承的两大体系:
- BeanFactory :bean工厂体系,获得了工厂所具有的功能。
- 查找对象
- 创建对象
- AliasRegistry + SingletonBeanRegistry:注册器的体系,获得了注册(存储)的功能。存储的地方有如下:
- BeanDefinitionMap:存储BeanDefinition的map
- SingletonObjects:单例池
- EarlySingleObjects:早期的单例池
- SingletonFactories:单例工厂池
ApplicationContext工厂
ApplicationContext也叫做应用的上下文,或者应用的环境。
在咱们开发的过程中,基本上使用的是这个工厂,因为这个工厂和Spring的核心容器 DefaultListableBeanFactory 功能类似,下面咱们要探讨问题如下:
- ApplicationContext 和 DefaultListableBeanFactory 有什么关系。
- 为什么在开发过程中要使用 ApplicationContext 工厂
ApplicationContext类图:
ApplicationContext的能力:
从上图我们可以知道,ApplicationContext 是 BeanFactory 的子接口,所以ApplicationContext 也具有 BeanFactory 的能力。
而作为子类的ApplicationContext 显然会具有比父类 BeanFactory 更多的功能。扩展点如下:
- EnvironmentCapable:具有环境感知的能力。配置文件中可以配置profile标签,分别可以配置dev(开发环境),product(产品环境,线上环境)
- ListableBeanFactory:这个工厂内部提供了一些方法,能更方便的展示bean的信息,对bean进行判断。
- HierarchicalBeanFactory:具有父子容器的能力。
- MessageSource:处理消息的能力,与事件发布是一对,一个发布,一个接收。
- ApplicationEventPublisher:事件发布的功能。
- ResourcePatternResolver:处理资源更加方便。例如:xml,Configuration配置类。
- BeanFactory:查找对象,创建对象。
但是从目前来看ApplicationContext扩展了这么多的能力,但是却比DefaultListableBeanFactory少了registry(注册)的能力,而没有registry的能力ApplicationContext就无法存储这些bean的信息。ApplicationContext并没有继承任何registry的接口,那么spring是怎么让ApplicationContext具有注册的能力的呢?
Spring中如果A类如果想拥有B类的能力,有两种方式可以使用:
- 通过继承的方式:A类继承B类。
- 通过成员变量的方式:A类中设置一个B类型的成员变量,然后将B类注入进A类。
因为单继承的原因,Spring这里使用的是通过成员变量的方式进行的。
所以大家思维发散一下。DefaultListableBeanFactory有registry的能力,ApplicationContext如果想拥有这个能力,是不是可以在ApplicationContext中缓存一个DefaultListableBeanFactory类型的成员变量呢。
很显然Spring就是这么做的。大家可以找到ApplicationContext接口,这个接口并没有直接存储DefaultListableBeanFactory,而是ApplicationContext接口的实现类所继承的类存储起来的。下面举个例子:
通过这个类图可以知道,ClassPathXmlApplicationContext是ApplicationContext的一个子实现,而通过继承以及实现的关系,这个子实现继承了AbstractRefreshableApplicationContext,而这个类就存储了DefaultListableBeanFactory。
看一下AbstractRefreshableApplicationContext这个类的源码:
里面清晰的能看到有个成员变量DefaultListableBeanFactory。
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
@Nullable
private Boolean allowBeanDefinitionOverriding;
@Nullable
private Boolean allowCircularReferences;
@Nullable
private volatile DefaultListableBeanFactory beanFactory;
public AbstractRefreshableApplicationContext() {
}
public AbstractRefreshableApplicationContext(@Nullable ApplicationContext parent) {
super(parent);
}
public void setAllowBeanDefinitionOverriding(boolean allowBeanDefinitionOverriding) {
this.allowBeanDefinitionOverriding = allowBeanDefinitionOverriding;
}
public void setAllowCircularReferences(boolean allowCircularReferences) {
this.allowCircularReferences = allowCircularReferences;
}
protected final void refreshBeanFactory() throws BeansException {
if (this.hasBeanFactory()) {
this.destroyBeans();
this.closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = this.createBeanFactory();
beanFactory.setSerializationId(this.getId());
this.customizeBeanFactory(beanFactory);
this.loadBeanDefinitions(beanFactory);
this.beanFactory = beanFactory;
} catch (IOException var2) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var2);
}
}
protected void cancelRefresh(BeansException ex) {
DefaultListableBeanFactory beanFactory = this.beanFactory;
if (beanFactory != null) {
beanFactory.setSerializationId((String)null);
}
super.cancelRefresh(ex);
}
protected final void closeBeanFactory() {
DefaultListableBeanFactory beanFactory = this.beanFactory;
if (beanFactory != null) {
beanFactory.setSerializationId((String)null);
this.beanFactory = null;
}
}
protected final boolean hasBeanFactory() {
return this.beanFactory != null;
}
public final ConfigurableListableBeanFactory getBeanFactory() {
DefaultListableBeanFactory beanFactory = this.beanFactory;
if (beanFactory == null) {
throw new IllegalStateException("BeanFactory not initialized or already closed - call 'refresh' before accessing beans via the ApplicationContext");
} else {
return beanFactory;
}
}
protected void assertBeanFactoryActive() {
}
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(this.getInternalParentBeanFactory());
}
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
if (this.allowBeanDefinitionOverriding != null) {
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.allowCircularReferences != null) {
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
}
}
protected abstract void loadBeanDefinitions(DefaultListableBeanFactory var1) throws BeansException, IOException;
}
基于上面这些能力的扩展,所以我们开发过程中会使用 ApplicationContext 工厂。