IoC 容器:Spring’s Inversion of Control (IoC) container
Spring 的核心功能是 IoC 容器 。spring-beans 和 spring-context 这两个库是 Spring IoC 容器的基础。 spring-core 是 Spring 的核心库,其他所有的 Spring 家族的库都会依赖 spring-core 。
BeanFactory
什么是 Bean :由 Spring IoC 容器管理的对象叫做 Bean 。Bean 是由 Spring IoC 容器 实例化、组装、管理 的对象;否则的话 Bean 只是应用中的一个普通对象。Bean 及其之间的依赖关系反映在容器使用的配置元数据中。
Spring 官方文档 中有介绍:BeanFactory 接口提供了一种高级的配置机制,能够管理任何类型的对象。
ApplicationContext
ApplicationContext 是 BeanFactory 的子接口,添加了更多功能:
- 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
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 方法,刷新容器,销毁之前的 BeanFactory 和 Beans ,重新创建。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 配置文件
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("services.xml");
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 ,比 ClassPathXmlApplicationContext ,FileSystemXmlApplicationContext 更加通用的基于 xml 配置文件的 ApplicationContext 。即可以在构造函数中指定配置数来源,使用的 Resource 类型的数组参数。而前两者都是使用String 类型的 configLocations 数组,即路径数组。
AnnotationConfigApplicationContext
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {}
这个也是用来处理我们项目中使用的注解的类,即将标注了 @Controller , @Component 等注解的类注册成 bean 。继承于 GenericApplicationContext ,并实现 AnnotationConfigRegistry 接口(AnnotationConfigRegistry 接口主要实现将给定的 beanDefinition 注册到绑定的 beanFactory 中)。
|