一、引言
根据上一篇Spring 源码分析(一)— IOC demo 可知,采用 xml 配置方式配置 Bean 的时候,入口类是 ClassPathXmlApplicationContext,就从 ClassPathXmlApplicationContext 入手,来进行分析。
二、ClassPathXmlApplicationContext 类图分析
如下,是 ClassPathXmlApplicationContext 类的继承关系图,通过分析该继承关系来一步步解析 Spring IOC 源码。
由类关系图可知,ClassPathXmlApplicationContext 最顶层父类接口有七个:
- BeanFactory
- Aware
- LifeCycle
- InitializingBean
- ResourceLoader
- ApplicationEventPublisher
- AutoCloseable
2.1. BeanFactory
/**
* 1. BeanFactory 是访问 Spring Bean 容器的根接口;
* 2. 定义根据 Bean name 获取 Bean 的接口;
*/
public interface BeanFactory {
BeanFactory 的 Implementation 如下:
ListableBeanFactory
/**
* 1. 扩展 BeanFactory 接口,可以枚举其所有的 Bean 实例;
* 2. 预加载所有 Bean 定义的 BeanFactory 实现(例如基于 XML 的工厂)可以实现此接口;
*/
public interface ListableBeanFactory extends BeanFactory {
HierarchicalBeanFactory
/**
* 1. 扩展 BeanFactory 的接口,实现了 Bean 工厂的分层,扩展了工厂分层的功能。
*/
public interface HierarchicalBeanFactory extends BeanFactory {
AutowireCapableBeanFactory
/**
* 1. 扩展 BeanFactory 接口,使有能力自动装配 ApplicationContext 管理之外的 Bean;
* 2. ApplicationContext 接口没有实现 AutowireCapableBeanFactory 接口,因为应用代码很少用到此功能,如果需要的话,可以调用 ApplicationContext 的 getAutowireCapableBeanFactory 方法,来获取此接口的实例。
*/
public interface AutowireCapableBeanFactory extends BeanFactory {
SimpleJndiBeanFactory
/**
* 1. 基于 JNDI 的 Spring BeanFactory 接口的简单实现;
* 2. 不支持枚举 bean 定义,因此不实现 org.springframework.beans.factory.ListableBeanFactory 接口。
*/
public class SimpleJndiBeanFactory extends JndiLocatorSupport implements BeanFactory {
StaticListableBeanFactory
/**
* 1. BeanFactory 的静态实现,它允许以编程方式注册现有的单例实例。
* 2. 不支持原型 Bean 或别名。
* 3. 作为 ListableBeanFactory 接口的简单实现的示例,管理现有的 Bean 实例,而不是基于 Bean 定义创建新的实例,并且不实现任何扩展的 SPI 接口(如 org.springframework.beans.factory.config.ConfigurableBeanFactory)。
* 4. 对于基于 Bean 定义的成熟工厂,请查看 DefaultListableBeanFactory。
*/
public class SimpleJndiBeanFactory extends JndiLocatorSupport implements BeanFactory {
StubBeanFactory
/**
* 1. StaticListableBeanFactory 的扩展,它实现了 AutowireCapableBeanFactory,以便允许 ApplicationContextAware 单例的 Bean 初始化;
*/
private class StubBeanFactory extends StaticListableBeanFactory implements AutowireCapableBeanFactory {
ConfigurableListableBeanFactory
/**
* 1. 大多数可列出的 Bean 工厂要实现的配置接口。除了 ConfigurableBeanFactory 之外,它还提供了分析和修改 Bean 定义以及预实例化单例的工具;
* 2. BeanFactory 的这个子接口不适合在普通应用程序代码中使用:对于典型用例,请坚持使用 org.springframework.beans.factory.BeanFactory 或 ListableBeanFactory;
* 3. 此接口只是为了允许框架内部即插即用,即使需要访问 Bean 工厂配置方法也是如此。
*/
public interface ConfigurableListableBeanFactory
extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory {
ApplicationContext
/**
* 1. 为应用程序提供配置的中央接口;
* 2. 在应用程序运行时是只读的,可以通过重新加载,来实现支持此功能;
* 3. 主要是各种属性的 get 方法;
*/
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
WebApplicationContext
/**
* 1. 专门为<font color="red"> Web 应用程序</font>提供配置的接口;
* 2. 从 WebApplicationContext 中可以获得 ServletContext 的引用;会定义一个众所周知的应用程序属性名称,根上下文必须在引导过程中绑定到该名称;
* 3. 与 ApplicationContext 一样,WebApplicationContext 也是分层的。每个应用程序都有一个根上下文,而应用程序中的每个 servlet(包括 MVC 框架中的调度程序 servlet)都有自己的子上下文;**
*/
public interface WebApplicationContext extends ApplicationContext {
ConfigurableApplicationContext
/**
* 1. SPI 接口将被大多数而非所有的应用程序上下文实现;
* 2. 此处封装了配置和生命周期方法,以避免它们对 ApplicationContext 客户端代码显而易见。当前方法应仅由启动和关闭代码使用;
* 3. 主要是各种属性的配置;
*/
public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {
AbstractApplicationContext
/**
* 1. ApplicationContext 的抽象实现;
* 2. 不强制要求用于配置的存储类型;只是实现通用上下文功能;
* 3. 使用模板方法设计模式,需要具体的子类来实现抽象方法;
*/
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
AbstractRefreshableApplicationContext
/**
* 1. ApplicationContext 实现的基类;
* 2. 主要是和容器的刷新与创建有关,调用 refreshBeanFactory 方法完成 applicationContext.xml 的解析操作,完成容器的初始化操作;
*/
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
AbstractRefreshableConfigApplicationContext
/**
* 1.用于添加对指定配置位置的通用处理;直白一点就是加载容器刷新时的配置文件的通用操作;
* 2.该类的两个子类,都是基于 xml 配置文件,将会有各自的定制的读取配置文件操作,所以该类提供的是读取配置文件通用操作,提供拓展点;
*/
public abstract class AbstractRefreshableConfigApplicationContext extends AbstractRefreshableApplicationContext
implements BeanNameAware, InitializingBean {
AbstractXmlApplicationContext
/**
* 1. 从包含 Bean 定义的 XML 文件加载 Bean 的方便基类;使用 XmlBeanDefinitionReader 进行解析 XML;
* 2. 子类只需要实现 getConfigResources 和/或 getConfigLocations 方法;
* 3. 它们可能会覆盖 getResourceByPath 钩子以以特定于环境的方式解释相对路径,和/或 getResourcePatternResolver 以扩展模式解析;
*/
public abstract class AbstractXmlApplicationContext extends AbstractRefreshableConfigApplicationContext {
FileSystemXmlApplicationContext
/**
* 1. 独立的 XML 应用程序上下文,从文件系统或 URL 获取上下文定义文件,将纯路径解释为相对文件系统位置(例如“mydir/myfile.txt”)。适用于测试工具以及独立环境;
* 2. 没有盘符的是项目工作目录,即项目的根目录;
* 3. 有盘符表示的是文件绝对路径, file: 前缀可加可不加;
* 4. 也可以使用 classpath 路径,如果要使用,需要前缀 classpath: ;
*/
public class FileSystemXmlApplicationContext extends AbstractXmlApplicationContext {
ClassPathXmlApplicationContext
/**
* 1. 从类路径中获取上下文定义文件,将普通路径解释为包含包路径的类路径资源名称;
* 2. 从 classpath 路径下加载 xml 配置文件;
* 3. 默认是指项目的 classpath 路径下面, classpath: 前缀是可加可不加的;
* 4. 如果要使用绝对路径,需要加上 file: 前缀,表示这是绝对路径;
*/
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
AbstractRefreshableWebApplicationContext
/**
* 1. AbstractRefreshableApplicationContext 的子类,AbstractRefreshableApplicationContext 的 Web 环境;
*/
public abstract class AbstractRefreshableWebApplicationContext extends AbstractRefreshableConfigApplicationContext
implements ConfigurableWebApplicationContext, ThemeSource {
AnnotationConfigWebApplicationContext
/**
* 1. org.springframework.web.context.WebApplicationContext 实现,处理 @Configuration @Component 以及使用jakarta.inject 注解的 JSR-330 兼容类;
* 2. 允许逐个注册类(将类名指定为配置位置)以及通过类路径扫描(将基本包指定为配置位置);
* 3. 这实质上相当于 Web 环境的 org.springframework.context.annotation.AnnotationConfigApplicationContext;
*/
public class AnnotationConfigWebApplicationContext extends AbstractRefreshableWebApplicationContext
implements AnnotationConfigRegistry {
XmlWebApplicationContext
/**
* 1. org.springframework.web.context.WebApplicationContext 实现,它从 XML 文档中获取其配置,由XmlBeanDefinitionReader 来解析;
* 2. 这实质上相当于 Web 环境的 org.springframework.context.support.GenericXmlApplicationContext;
* 3. 根 context 默认从 /WEB-INF/applicationContext.xml 获取配置文件;
*/
public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext {
GroovyWebApplicationContext
/**
* 1. org.springframework.web.context.WebApplicationContext 实现,它从 Groovy 文档中获取其配置,由 org.springframework.beans.factory.groovy.GroovyBeanDefinitionReader 来解析;
* 2. 这实质上相当于 Web 环境的 org.springframework.context.support.GenericGroovyApplicationContex;
* 3. 根 context 默认从 /WEB-INF/applicationContext.groovy 获取配置文件;
*/
public class GroovyWebApplicationContext extends AbstractRefreshableWebApplicationContext implements GroovyObject {
GenericApplicationContext
/**
* 1.通用的 ApplicationContext 实现;采用混合方式(XML、注解等)处理 bean 的定义,而不是采用特定的 bean 定义方式来创建bean;
* 2.内部有一个 DefaultListableBeanFactory 实例;实现 BeanDefinitionRegistry 接口,以便允许对其应用任何 Bean 定义读取器;
*/
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
GenericXmlApplicationContext
/**
* 1. 具有内置 XML 支持的便捷应用程序上下文;
* 2. 是 ClassPathXmlApplicationContext 和 FileSystemXmlApplicationContext 的灵活替代方案,可通过 setter 进行配置,最终 refresh() 调用激活上下文;
*/
public class GenericXmlApplicationContext extends GenericApplicationContext {
GenericGroovyApplicationContext
/**
* 1. org.springframework.context.ApplicationContext 实现,它扩展了 GenericApplicationContext 并实现了 GroovyObject,以便可以使用 Groovy 语法代替 getBean 来检索 bean;
*/
public class GenericGroovyApplicationContext extends GenericApplicationContext implements GroovyObject {
AnnotationConfigApplicationContext
/**
* 1. 注解配置的 ApplicationContext 实现;
* 2. 处理 @Configuration,包括使用 jakarta.inject 注解的纯 @Component 类型和符合 JSR-330 的类;
*/
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
ConfigurableWebApplicationContext
/**
* 1. ConfigurableApplicationContext 的 Web 实现;
*/
public interface ConfigurableWebApplicationContext extends WebApplicationContext, ConfigurableApplicationContext {
StaticApplicationContext
/**
* 1. ApplicationContext 实现,它支持以编程方式注册 bean 和消息,而不是从外部配置源读取 Bean 定义。主要用于测试;
*/
public class StaticApplicationContext extends GenericApplicationContext {
StubWebApplicationContext
/**
* 1. 接受对象实例注册的 Stub WebApplicationContext;
*/
class StubWebApplicationContext implements WebApplicationContext {
ConfigurableBeanFactory
/**
* 1.大多数 bean factories 要实现的配置接口。提供用于配置 Bean 工厂的工具,以及 BeanFactory 接口中的 Bean 工厂客户端方法。
* 2.此接口不适用于普通应用程序代码:坚持使用 BeanFactory 或 org.springframework.beans.factory.ListableBeanFactory 以满足典型需求;
* 3.此扩展接口只是为了允许框架内部即插即用和对 Bean 工厂配置方法的特殊访问;
*/
public class SimpleJndiBeanFactory extends JndiLocatorSupport implements BeanFactory
2.2. Aware
1.Spring 的依赖注入最大亮点就是所有的 Bean 对 Spring 容器的存在是没有意识的;
2.但是在实际项目中,我们不可避免的要用到 Spring 容器本身提供的资源,这时候要让 Bean 主动意识到 Spring 容器的存在,才能调用 Spring 所提供的资源,这就是 Spring Aware;
2.3. LifeCycle
1.定义启动/停止生命周期控制方法的通用接口;
public interface Lifecycle {
/**
* Start this component.
*/
void start();
/**
* Stop this component, typically in a synchronous fashion, such that the component is
* fully stopped upon return of this method.
*/
void stop();
/**
* Check whether this component is currently running.
*/
boolean isRunning();
}
2.4. InitializingBean
1.Spring 提供的拓展性接口,InitializingBean 接口为 Bean 提供了属性初始化后的处理方法,它只有一个 afterPropertiesSet() 方法,凡是继承该接口的类,在 Bean 的属性初始化后都会执行该方法,进行其总体配置和最终初始化验证;
public interface InitializingBean {
/**
* Invoked by the containing {@code BeanFactory} after it has set all bean properties
* and satisfied {@link BeanFactoryAware}, {@code ApplicationContextAware} etc.
* <p>This method allows the bean instance to perform validation of its overall
* configuration and final initialization when all bean properties have been set.
* @throws Exception in the event of misconfiguration (such as failure to set an
* essential property) or if initialization fails for any other reason
*/
void afterPropertiesSet() throws Exception;
}
2.5. ResourceLoader
1.用于加载资源(例如,类路径或文件系统资源)的策略接口;
1.Spring 中整合了获取资源的工具,就是使用 Resource 接口。此接口是 Spring 为了统一读取诸如本地文件、classpath 项目路径下的文件、url 互联网上的文件等不同类型渠道的资源,封装隐藏如打开流、关闭流、报错处理等大量重复模板代码,而专程设计提供的接口类。
2.而 Spring 框架为了更方便的获取资源,尽量弱化程序员对各个 Resource 接口实现类的感知与分辨,降低学习与使用成本,定义了另一个接口,就是:ResourceLoader接口。
public interface ResourceLoader {
/** Pseudo URL prefix for loading from the class path: "classpath:". */
String CLASSPATH_URL_PREFIX = ResourceUtils.CLASSPATH_URL_PREFIX;
/**
* Return a {@code Resource} handle for the specified resource location.
*/
Resource getResource(String location);
/**
* Expose the {@link ClassLoader} used by this {@code ResourceLoader}.
*/
@Nullable
ClassLoader getClassLoader();
}
2.6. ApplicationEventPublisher
1.封装事件发布功能的接口;
2.函数式接口;
@FunctionalInterface
public interface ApplicationEventPublisher {
/**
* Notify all <strong>matching</strong> listeners registered with this
* application of an application event. Events may be framework events
* (such as ContextRefreshedEvent) or application-specific events.
*/
default void publishEvent(ApplicationEvent event) {
publishEvent((Object) event);
}
/**
* Notify all <strong>matching</strong> listeners registered with this
* application of an event.
*/
void publishEvent(Object event);
}
2.7. AutoCloseable
1.当一个资源类实现了该接口 close 方法,在使用 try-with-resources 语法创建的资源抛出异常后,JVM 会自动调用 close 方法进行资源释放;当没有抛出异常正常退出 try 代码块时也会自动调用 close 方法。像数据库链接类 Connection,io 类 InputStream 或 OutputStream 都直接或者间接实现了该接口;
public interface AutoCloseable {
/**
* Closes this resource, relinquishing any underlying resources.
* This method is invoked automatically on objects managed by the
* {@code try}-with-resources statement.
*/
void close() throws Exception;
}