最近在看Spring IOC原理的源码,在此记录一下。
一. 两种容器类型的类关系图
BeanFactory 和 ApplicationContext是两种体系的IOC容器,ApplicationContext 继承了BeanFactory的功能,且根据不同层次提供了对应的上下文,在功能实现上复杂了很多。详细区别可以参考:www.jianshu.com/p/fd8e441b9…
按照Spring5.3.9的依赖,梳理了一下两种体系常见的接口(绿色)、抽象类(黄色)和实现类(蓝色)
1.1 BeanFactory
1.2 ApplicationContext(已去除ReactiveWeb类关系)
二、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应用上下文。