Spring - IoC 容器之 ApplicationContext 的各种实现类

IoC 容器:Spring’s Inversion of Control (IoC) container

Spring 的核心功能是 IoC 容器spring-beansspring-context 这两个库是 Spring IoC 容器的基础。
spring-core 是 Spring 的核心库,其他所有的 Spring 家族的库都会依赖 spring-core


BeanFactory

什么是 Bean:由 Spring IoC 容器管理的对象叫做 BeanBean 是由 Spring IoC 容器 实例化、组装、管理 的对象;否则的话 Bean 只是应用中的一个普通对象。Bean 及其之间的依赖关系反映在容器使用的配置元数据中。

Spring 官方文档 中有介绍:BeanFactory 接口提供了一种高级的配置机制,能够管理任何类型的对象。

ApplicationContext

ApplicationContextBeanFactory 的子接口,添加了更多功能:

  • Easier integration with Spring’s AOP features(更容易与 Spring AOP 特性集成)
  • Message resource handling (for use in internationalization)(消息资源处理(国际化))
  • Event publication(事件发布)
  • Application-layer specific contexts such as the WebApplicationContext for use in web applications.(应用层特定的上下文,例如用于 web 应用的 WebApplicationContext)
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
		MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
}

BeanFactory 提供了配置框架和基本功能,ApplicationContext 添加了更多企业级的功能,是前者的超集。

在这里插入图片描述

配置 IoC 容器 的元数据

一个类是如何加入到 IoC 容器 中的呢,换句话说:IoC 容器 是怎么识别一个类是普通类还是 Bean 呢?

传统的方式是使用 xml 配置文件(还可以使用 Java 注解 或 Java 代码)来声明各种 元数据(声明为 Bean 及其之间的依赖关系),之后在 IoC 容器创建并初始化的时候,会读取配置的 元数据 来 初始化、配置、装配 这些 Bean

在 web 应用程序中,我们通常会 在 web.xml 中配置 IoC 容器的加载器(org.springframework.web.context.ContextLoaderListener)来实例化 ApplicationContext

初始化 IoC 容器

Spring 提供了几种 ApplicationContext 的几种实现:

ConfigurableApplicationContext

public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {}

ConfigurableApplicationContext 作为 ApplicationContext 的派生接口,定义了一些非通用的方法。符合面向对象的7大设计原则之一的接口隔离原则。

注意:这里定义的 refresh 方法,不支持多次调用。实现类中的这个方法自然也不支持多次调用,但是 AbstractRefreshableApplicationContext 中提供了多次调用的方法。

在这里插入图片描述

AbstractApplicationContext

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {}

ConfigurableApplicationContext 接口的抽象实现类。

其中的 refresh 方法,是 IoC 容器启动的骨架实现,使用了 模板设计模式。提供对 ConfigurableApplicationContext 接口的 refresh 方法的模板实现,即:定义了 ApplicationContext 的启动步骤,但是不提供具体每一步的实现,由子类实现。

在这里插入图片描述
比如其中的 postProcessBeanFactory 方法:

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	}

AbstractRefreshableApplicationContext

public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
	@Nullable
	// 允许重复Bean定义覆盖
	private Boolean allowBeanDefinitionOverriding;

	@Nullable
	// 允许循环引用
	private Boolean allowCircularReferences;
	
	...
	@Override
	protected final void refreshBeanFactory() throws BeansException {
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
			customizeBeanFactory(beanFactory);
			loadBeanDefinitions(beanFactory);
			this.beanFactory = beanFactory;
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}
	...
}

继承 AbstractApplicationContext 抽象类,主要提供可多次重复调用 refresh 方法,刷新容器,销毁之前的 BeanFactoryBeans,重新创建。ConfigurableApplicationContext 接口的定义,默认是不支持多次调用 refresh 方法的,多次调用则抛 IllegalStateException 异常。

AbstractRefreshableConfigApplicationContext

public abstract class AbstractRefreshableConfigApplicationContext extends AbstractRefreshableApplicationContext
		implements BeanNameAware, InitializingBean {

	@Nullable
	private String[] configLocations;
	...
}

继承 AbstractRefreshableApplicationContext 抽象类,主要作用是定义数组类型的 configLocations 变量,用于加载多个 xml 文件来配置 IoC 容器。

AbstractXmlApplicationContext

public abstract class AbstractXmlApplicationContext extends AbstractRefreshableConfigApplicationContext {}

继承 AbstractRefreshableConfigApplicationContext,指定使用 xml 文件保存配置,有两个实现类:

  • ClassPathXmlApplicationContext:指定从类路径下加载 xml 配置文件
  • FileSystemXmlApplicationContext:指定从文件系统加载 xml 配置文件
// 通过加载类路径下的 xml 配置文件创建并初始化 IoC 容器
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("services.xml");
// 获取 IoC 容器中定义的 Beans 的 name
String[] beanNames = applicationContext.getBeanDefinitionNames();
for (String beanName : beanNames) {
    System.out.println(beanName);
}

GenericApplicationContext

public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {}

继承 AbstractApplicationContext,故不具备上面的 Config,Refreshable 功能。而 Bean 的注册,是通过实现 BeanDefinitionRegistry 接口来提供往内部的 beanFactory 注入 beanDefinitions,而 beanDefinitions 的来源则是通过 BeanDefinitionParser 解析,如 xml 文件来获取的。不支持重复调用 refresh

GenericXmlApplicationContext:继承于 GenericApplicationContext,比 ClassPathXmlApplicationContextFileSystemXmlApplicationContext 更加通用的基于 xml 配置文件的 ApplicationContext。即可以在构造函数中指定配置数来源,使用的 Resource 类型的数组参数。而前两者都是使用String 类型的 configLocations 数组,即路径数组。

AnnotationConfigApplicationContext

public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {}

这个也是用来处理我们项目中使用的注解的类,即将标注了 @Controller, @Component 等注解的类注册成 bean。继承于 GenericApplicationContext,并实现 AnnotationConfigRegistry 接口(AnnotationConfigRegistry 接口主要实现将给定的 beanDefinition 注册到绑定的 beanFactory 中)。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值