Spring5.X IOC容器源码分析 BeanFactory和ApplicationContext

159 阅读9分钟

最近在看Spring IOC原理的源码,在此记录一下。

一. 两种容器类型的类关系图

BeanFactory 和 ApplicationContext是两种体系的IOC容器,ApplicationContext 继承了BeanFactory的功能,且根据不同层次提供了对应的上下文,在功能实现上复杂了很多。详细区别可以参考:www.jianshu.com/p/fd8e441b9…

按照Spring5.3.9的依赖,梳理了一下两种体系常见的接口(绿色)、抽象类(黄色)和实现类(蓝色)

1.1 BeanFactory

绘图1.jpg

1.2 ApplicationContext(已去除ReactiveWeb类关系)

绘图3.jpg

二、BeanFactory体系类说明

2.1 BeanFactory

该接口就是一个容器的根接口,是一个简单的Bean工厂,给后续容器的实现提供一个规范;其提供的方法如下:

public interface BeanFactory {
 
	// 用于区分是FactoryBean还是具体的实例
    String FACTORY_BEAN_PREFIX = "&";
 
	// 根据bean名称返回指定bean的实例
    Object getBean(String name) throws BeansException;
 
	// 根据bean名称和类型,返回指定bean的实例
    <T> T getBean(String name, Class<T> requiredType) throws BeansException;
 
	// 根据bean名称返回指定bean的实例,并根据参数args执行构造参数
    Object getBean(String name, Object... args) throws BeansException;
 
	// 根据bean类型,返回指定bean的实例
    <T> T getBean(Class<T> requiredType) throws BeansException;
 
	// 根据bean类型,返回指定bean的实例,并根据参数args执行构造参数
    <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
 
	// 返回指定bean的提供程序
    <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
 
	// 根据bean要匹配的类型, 返回指定bean的提供程序
    <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);
 
	// 此bean工厂是否包含bean
    boolean containsBean(String name);
 
	// 判断该Bean是否单例单例
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
 
	// 判断该Bean是否原型模式
    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
 
	// 检查具有给定名称的bean是否与指定的类型匹配
    boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
 
	// 检查具有给定名称的bean是否与指定的类型匹配
    boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
 
	// 获取给定名称的bean的类型。
    Class<?> getType(String name) throws NoSuchBeanDefinitionException;
	
	// 返回给定bean名称的别名
    String[] getAliases(String name);
}

BeanFactory和FactoryBean的关系可参照:www.cnblogs.com/aspirant/p/… 四种getBean的使用可以参照:www.jianshu.com/p/01bee649a…

2.2 HierarchicalBeanFactory

该接口拓展了层级的概念:如果容器有层级,都需要继承或实现该类去获取父容器。

但是设置父容器的方法在其子接口ConfigurableBeanFactory中。

父子容器概念可以参照:www.jianshu.com/p/ae413c7c3…

2.3 AutowireCapableBeanFactory

该接口提供了容器自动装配的能力。也可以自己实现该接口,给非容器的bean进行依赖注入

方法的实现逻辑说明可以参照:www.cnblogs.com/houzheng/p/…

2.4 ListableBeanFactory

该接口提供了列举Bean的能力,但是获取不到父容器的Bean

2.5 AliasRegistry

该接口提供了别名注册的能力。其提供的方法如下:

public interface AliasRegistry {
 
    // 注册表中给name注册一个别名alias, 如果别名已存在,报错IllegalStateException
    void registerAlias(String name, String alias);
 
    // 移除注册表中的别名alias吗。如果别名不存在,报错IllegalStateException 
    void removeAlias(String alias);
 
    // 校验注册表中是否存在别名name
    boolean isAlias(String name);
 
    // 在注册表中获取给定那么的所有别名信息
    String[] getAliases(String name);
}

2.6 BeanDefinitionRegistry

该接口是对BeanDefinition(描述了一个Bean的实例)的注册,增删等操作接口。它继承了AlisasRegistry,使得BeanDefinition也有了别名管理的能力。其提供的方法如下:

public interface BeanDefinitionRegistry extends AliasRegistry {

// 往注册表中注册一个新的 BeanDefinition 实例 
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionStoreException;

// 移除注册表中已注册的 BeanDefinition 实例
void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

// 从注册中取得指定的 BeanDefinition 实例
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

// 判断 BeanDefinition 实例是否在注册表中(是否注册)
boolean containsBeanDefinition(String beanName);

// 取得注册表中所有 BeanDefinition 实例的 beanName(标识)
String[] getBeanDefinitionNames();

// 返回注册表中 BeanDefinition 实例的数量
int getBeanDefinitionCount();

// beanName(标识)是否被占用
boolean isBeanNameInUse(String beanName);

} BeanDefinition是什么,可以参考:www.jianshu.com/p/ab5911816…

2.7 SimpleAliasRegistry

对于AliasRegistry接口的简单实现,具体方法含义可以参考:blog.csdn.net/D_FengDong/…

2.8 SingletonBeanRegistry

提供了单例bean注册和访问的统一方法。其提供的方法如下:

public interface SingletonBeanRegistry {
	//在给定的bean名称下,在bean注册表中将给定的现有对象注册为singleton。
	void registerSingleton(String beanName, Object singletonObject);
	//检查此注册表是否包含具有给定名称的单例实例。
	boolean	containsSingleton(String beanName);
	//返回在此注册表中注册的单例bean的名称。
	String[] getSingletonNames();
	//返回在给定名称下注册的(原始)单例对象。
	Object getSingleton(String beanName);
	//返回在此注册表中注册的单例bean的数量。
	int	getSingletonCount();
	//返回此注册表使用的单例互斥锁
	Object getSingletonMutex();
}

2.9 DefaultSingletonBeanRegistry

该接口继承了SimpleAliasRegistry类,实现了SingletonBeanRegistry接口。用于处理单例bean的注册,销毁等功能。 具体的方法实现可以参考:www.cnblogs.com/insaneXs/p/…

2.10 FactoryBeanRegistrySupport

该抽象类通过一个ConcurrentHashMap提供了单例FactoryBean的缓存功能。 具体方法实现可以参考:blog.csdn.net/cgsyck/arti…

2.11 ConfigurableBeanFactory

该接口提供了工厂创建、注册一个Bean的众多细节方法。 具体方法可以参考:blog.csdn.net/u013412772/…

2.12 AbstractBeanFactory

该抽象类继承了FactoryBeanRegistrySupport,实现了接口ConfigurableBeanFactory中单例的创建、注册、获取(四个getBean的实现)等方法的实现。 具体方法实现可以参考:segmentfault.com/a/119000002…

2.13 AbstractAutowireCapableBeanFactory

该抽象类继承了AbstractBeanFactory,实现了接口AutowireCapableBeanFactory中的自动装配功能。 具体方法实现可以参考:segmentfault.com/a/119000002…

2.14 ConfigurableListableBeanFactory

该接口继承了ListableBeanFactory、AutowireCapableBeanFactory 和 ConfigurableBeanFactory三个接口。并提供了BeanDefinition的获取,预加载等功能方法。 具体方法实现可以参考:blog.csdn.net/u013412772/…

2.15 DefaultListableBeanFactory

该方法继承了AbstractAutowireCapableBeanFactory,实现了接口BeanDefinitionRegistry和ConfigurableListableBeanFactory提供的所有方法,如补充了单例的获取(两个getBean的实现) 在ApplicationContext体系中: XmlWebApplicationContext 用了 DefaultListableBeanFactory + XmlBeanDefinitionReader,后者专门用于读取XML配置 AnnotationConfigApplicationContext 用了 DefaultListableBeanFactory + AnnotatedBeanDefinitionReader,后者专门用于读取注解配置

3.ApplicationContext体系类说明

3.1 ApplicationContext

该接口继承了 EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver。 -ListableBeanFactory接口提供了访问应用程序组件的Bean工厂方法 -ResourcePatternResolver接口提供了返回指定路径下所有的资源对象的方法。 -ApplicationEventPublisher接口提供了事件发布能力。 -MessageSource接口提供了消息的解析和国际化能力。 -EnvironmentCapable接口提供了访问Environment对象能力。

3.2 ConfigurableApplicationContext

该接口继承了ApplicationContext, Lifecycle, Closeable接口。提供了应用上下文的配置以及控制生命周期的方法。

public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {
	
	// 设置容器的唯一ID
    void setId(String id);
 
	// 设置此容器的父容器
    void setParent(ApplicationContext parent);
 
	// 设置容器的Environment变量
    void setEnvironment(ConfigurableEnvironment environment);
 
	// 以ConfigurableEnvironment的形式返回此容器的环境变量。
    ConfigurableEnvironment getEnvironment();
	
	// 5.3版本后新增: 设置ApplicationStartup
	void setApplicationStartup(ApplicationStartup applicationStartup);
 
	// 5.3版本后新增 用ApplicationStartup来标记应用程序启动期间的步骤
	ApplicationStartup getApplicationStartup();
 
	// 在读取应用上下文配置的时候,向此容器中增加BeanFactoryPostProcessor。增加的Processor会在容器refresh的时候使用。
    void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor);
 
	// 向容器增加一个ApplicationListener,增加的Listener用于发布上下文事件如refresh和shutdown等,如果此上下文还没有启动,那么在此注册的Listener将会在上下文refresh的时候,全部被调用;
    // 如果上下文已经是active状态的了,就会在multicaster中使用
    void addApplicationListener(ApplicationListener<?> listener);
 
	// 向容器中注入给定的ProtocolResolver,允许多个实例同时存在。
    void addProtocolResolver(ProtocolResolver resolver);
 
	// 加载资源配置文件(XML、properties,Whatever)刷新Bean,方法完成后,所有bean都以被初始化好
    void refresh() throws BeansException, IllegalStateException;
 
	// 向JVM注册一个回调函数,用以在JVM关闭时,销毁此应用上下文。
    void registerShutdownHook();
 
	// 关闭此应用上下文
    void close();
 
	// 检测此FactoryBean是否被启动过。
    boolean isActive();
 
	// 返回此应用上下文的容器。
    ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
}

3.2 WebApplicationContext(Spring-Web)

该接口来自web包,继承了ApplicationContext,只提供了获取ServletContext的方法。

3.3 WebServerApplicationContext(Spring-Web)

该接口来自web包,继承了ApplicationContext,提供了获取WebServer,获取WebServer上下文命名空间的方法。

3.4 ConfigurableWebApplicationContext

该接口来自web包,继承了WebApplicationContext接口,提供了配置ServletContext的方法。

3.5 ConfigurableWebServerApplicationContext

该接口来自web包,继承了WebServerApplicationContext,提供了配置WebServer,配置WebServer上下文命名空间的方法。

3.6 AbstractApplicationContext

该抽象类继承了DefaultResourceLoader,实现了ConfigurableApplicationContext接口中的所有方法。 DefaultResourceLoader是Spring资源加载模块的实现类,详细说明可以参考:blog.csdn.net/seasonsbin/…

3.7 AbstractRefreshableApplicationContext

该抽象类继承了AbstractApplicationContext,实现了父类中声明的refreshBeanFactory、closeBeanFactory等抽象方法用于可重复刷新上下文。 该类中声明了一个DefaultListableBeanFactory对象。用于存储上文中的bean工厂。

3.8 GenericApplicationContext

该抽象类继承了AbstractApplicationContext,实现了BeanDefinitionRegistry接口。提供了通用的beanDefinition注册的功能。

与AbstractRefreshableApplicationContext不同的是,该类声明的bean工厂是不可重复刷新的

3.9 AbstractXmlApplicationContext

该抽象类继承了AbstractRefreshableApplicationContext,提供了对于ApplicationContext.xml配置文件的解析能力

3.10 AbstractRefreshableWebApplicationContext

该抽象类继承了AbstractRefreshableApplicationContext,实现了ConfigurableWebApplicationContext接口。

该类实现了AbstractApplicationContext类的抽象方法postProcessBeanFactory,向postPorcessor注册了一个ServletContextAwareProcessor对象。用于向Web应用上下文中织入ServletContext和ServletConfig。

3.11 AnnotationConfigRegistry

该接口是用于注解配置应用上下文的通用接口,拥有一个注册配置类和扫描配置类的方法。

3.12 FileSystemXmlApplicationContext

该类继承了AbstractXmlApplicationContext,是系统路径下的xml配置应用上下文实现类。

3.13 ClassPathXmlApplicationContext

该类继承了AbstractXmlApplicationContext,是相对路径下的xml配置应用上下文实现类。

3.14 XmlWebApplicationContext

该类继承了AbstractRefreshableWebApplicationContext,是xml配置的web应用上下文实现类。

默认读取/WEB-INF/applicationContext.xml的配置解析

3.15 AnnotationConfigWebApplicationContext

该类继承了AbstractRefreshableWebApplicationContext,是注解配置的web应用上下文实现类。

3.16 GenericXmlApplicationContext

该类继承了GenericApplicationContext,是xml配置的应用上下文,但是相比FileSystemXmlApplicationContext和ClassPathXmlApplicationContext更加灵活 可以任意配置读取路径和DefinitionReader,使用示例如下:

GenericApplicationContext ctx = new GenericXmlApplicationContext();
//使用XmlBeanDefinitionReader
XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx);
//加载ClassPathResource
xmlReader.loadBeanDefinitions(new ClassPathResource("applicationContext.xml"));
PropertiesBeanDefinitionReader propReader = new PropertiesBeanDefinitionReader(ctx);
propReader.loadBeanDefinitions(new ClassPathResource("bean.properties"));
//调用Refresh方法
ctx.refresh();
//和其他ApplicationContext方法一样的使用方式
MyBean myBean = (MyBean) ctx.getBean("myBean");

3.17 AnnotationConfigApplicationContext

该类继承了GenericApplicationContext,是注解配置的应用上下文实现类。 用法可以参考:www.cnblogs.com/ustc-anmin/…

3.18 StaticApplicationContext

该类继承了GenericApplicationContext,可以支持通过编程的方式注入bean到应用上下文。 用法可以参考:blog.csdn.net/hotbain/art…

3.19 StaticWebApplicationContext

该类继承了StaticApplicationContext,实现了ConfigurableWebApplicationContext接口,可以支持通过编程的方式注入bean到web应用上下文。

3.20 GenericWebApplicationContext

该类继承了GenericApplicationContext,实现了ConfigurableWebApplicationContext接口,是一个通用的web应用实现类。

3.21 AnnotationConfigServletWebApplicationContext

该类继承了GenericWebApplicationContext,可以通过注解的方式创建一个Web应用上下文

3.22 ServletWebServerApplicationContext

该类继承了GenericWebApplicationContext,实现了ConfigurableWebServerApplicationContext。 重写GenericWebApplicationContext的onFresh方法,会去创建WebServer启动,这也是SpringBoot的web项目不需要tomcat服务器就能启动的原因。

3.23 AnnotationConfigServletWebServerApplicationContext

该类继承了ServletWebServerApplicationContext方法,支持注解方式配置web应用上下文。

3.24 XmlServletWebServerApplicationContext

该类继承了ServletWebServerApplicationContext方法,支持xml方式配置web应用上下文。