Spring源码之ApplicationContext(六)

mac2024-06-03  33

前言: Spring的两大容器ApplicationContext与BeanFactory,顾名思义ApplicationContext是应用的上下文,BeanFactory是bean工厂。 但是从代码层面来看ApplicationContext接口是继承了BeanFactory接口的,也就是说两者都有做容器的能力,而ApplicationContext 相对BeanFactory而言他又多了一些其他的功能,所以在我们常用的web应用中,ApplicationContext应用上下文是作为容器的最佳选择, 当然spring也是希望我们这么用的。 本文将简单阐述一下两个容器的区别,着重在源码层面进行分析两个容器的相辅相成及在spring生态中起到的重要作用。

0.简单阐述ApplicationContext与BeanFactory两种容器的区别

1.作用不同,BeanFactory是用来读取bean的配置文件,管理bean的加载,实例化及其整个生命周期并维护其依赖关系 ApplicationContext除了拥有BeanFactory的所有功能外,还有更完整的供应用使用的框架功能,如国际化,aop,事务等 2.bean的初始化时机不同,BeanFactory在启动的时候不会初始化bean实例,只有在使用bean的时候才会初始化 ApplicationContext是在启动的时候就初始化了所有的单例bean 综上所述,关于两个容器的选择,则需要按需选取,对于我们常用的web应用,肯定是选取ApplicationContext容器,因为他就是为了应用而生 而在两个容器都可以使用的情况下,我们就结合我们的硬件来考虑,需要占用较小资源的选择BeanFactory,反之选择ApplicationContext

ApplicationContext应用上下文 从字面来看不太好懂,应用就是咱们常说的web应用或者是其他种类的提供服务的一个程序,而上下文咱们可以通俗的理解为他是一个应用的环境或者是容器,意思是拿到这个context对象了,就相当于咱们拥有掌控这个应用的能力了。 如果把应用比作是一个人的话,那么ApplicationContext就是人的大脑或者是思想,他掌控着整个应用的生命周期。

1.1.ApplicationContext的接口继承关系 关于ApplicationContext的接口定义关系如下图,两个直接的继承接口,一个间接的继承接口。 其中ConfigurableApplicationContext从字面来看是具有配置功能的ApplicationContext,主要是为应用上下文提供配置能力 WebApplicationContext是具体web功能的ApplicationContext,他能获取ServletContext ConfigurableWebApplicationContext是结合上面两个接口的功能,配置ServletContext以及一些其他的web应用配置 1.1.1.先上ApplicationContext接口本尊,关于其父接口此处不作详细说明了,有兴趣的可以自行研究

本接口新定义的方法主要有: 1.getId()获取context的id 2.getApplicationName()获取应用名称 3.getStartupDate()获取启动时间 4.getParent()获取父容器 5.getAutowireCapableBeanFactory()获取有自动装配能力的BeanFactory public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver { @Nullable String getId(); String getApplicationName(); String getDisplayName(); long getStartupDate(); @Nullable ApplicationContext getParent(); AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException; }

1.1.2.接下来看ConfigurableApplicationContext,主要提供了几个配置应用上下文的方法

本接口新定义的方法主要有: 1.setId(String id)设置id 2.setParent(@Nullable ApplicationContext parent)设置父容器 3.setEnvironment(ConfigurableEnvironment environment)设置环境变量 4.ConfigurableEnvironment getEnvironment()获取环境变量,重写了父接口的方法,此处我理解是为了返回 ConfigurableEnvironment类型的环境变量,这样相当于扩展了Environment。 5.addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor)添加bean工厂后置处理器 6.addApplicationListener(ApplicationListener<?> listener)添加监听器 7.addProtocolResolver(ProtocolResolver resolver)添加协议解析器 8.refresh()刷新容器 9.registerShutdownHook()关闭容器,这是一种推荐的关闭方式 10.close()关闭 11.isActive()是否活动状态 12.getBeanFactory()获取BeanFactory public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable { //常量的定义省略不作解释 void setId(String id); void setParent(@Nullable ApplicationContext parent); void setEnvironment(ConfigurableEnvironment environment); @Override ConfigurableEnvironment getEnvironment(); void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor); void addApplicationListener(ApplicationListener<?> listener); void addProtocolResolver(ProtocolResolver resolver); void refresh() throws BeansException, IllegalStateException; void registerShutdownHook(); @Override void close(); boolean isActive(); ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException; }

1.2.ApplicationContext的实现类继承关系 ApplicationContext的实现类按是否可实例化分为:抽象实现类与具体实现类 按功能分类的话可分为:可刷新的与普通的,这里的可刷新是指刷新BeanFactory,每次刷新都会销毁原工厂,创建新工厂 1.2.1.先详细解读一下ApplicationContext的第一个抽象实现类AbstractApplicationContext, 此类中的实现了应用上下文的大部分主流程方法.

此抽象类的功能就是对所有接口的方法进行实现,大体的流程这里不作说明,前文已经阐述了 这里值得注意的地方就是在最后部分有三个抽象方法: protected abstract void refreshBeanFactory()//刷新BeanFactory protected abstract void closeBeanFactory()//关闭BeanFactory public abstract ConfigurableListableBeanFactory getBeanFactory()//获取BeanFactory 他们的抽象化我个人认为是为了扩展,这些会在后面几个实现类中体现 public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext { //详细源码不贴出来了 }

1.2.2.下面介绍普通的应用上下文GenericApplicationContext,这里的普通就是他在初始化的时候直接new了BeanFactory

1.构造方法,针对不同的用途: GenericApplicationContext()//空参,自己new的BeanFactory GenericApplicationContext(DefaultListableBeanFactory beanFactory)//传入一个BeanFactory GenericApplicationContext(ApplicationContext parent)//传入一个父容器,子容器的BeanFactory还是自己new GenericApplicationContext(DefaultListableBeanFactory beanFactory, ApplicationContext parent)//传入父容器与BeanFactory 2.实现了AbstractApplicationContext中的抽象方法 refreshBeanFactory()//无具体实现内容,只是替换了id cancelRefresh()//重写增强方法,将id置为null closeBeanFactory()//将id置为null,没有完全的关闭销毁 getBeanFactory()//直接返回 3.实现了BeanDefinitionRegistry接口 此接口的作用,顾名思义就是BeanDefinition的注册,所以GenericApplicationContext拥有了操作BeanDefinition的功能,也就完整了作为应用容器的能力 下面列举比较重要的方法: registerBeanDefinition()//注册BeanDefinition,是调用BeanDefinition里面的方法,后面说BeanFactory的时候详细讲解 public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry { //... }

1.2.3.具有刷新功能的抽象应用上下文AbstractRefreshableApplicationContext

AbstractRefreshableApplicationContext最大的特点就说有刷新容器上 在其父类AbstractApplicationContext的refresh()方法被调用时, 会调用到refreshBeanFactory()方法,进而重新创建一个bean工厂。 相对于GenericApplicationContext中refreshBeanFactory()方法的实现,该类中增加了销毁原工厂,创建新工厂的功能 public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext { //1.判断context中是否已有BeanFactory //2.有的话就销毁,关闭旧的BeanFactory //3.创建新的BeanFactory @Override protected final void refreshBeanFactory() throws BeansException { if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory); loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } } }

1.2.4.其他实现类的用途

1.具有刷新能力的抽象ApplicationContext AbstractRefreshableApplicationContext的子类 AbstractRefreshableConfigApplicationContext扩展配置功能 AbstractRefreshableWebApplicationContext扩展Web功能 AnnotationConfigWebApplicationContext WEB应用直接可以使用的基于注解的ApplicationContext XmlWebApplicationContext WEB应用直接可以使用的基于XML配置的ApplicationContext AbstractXmlApplicationContext 基于XML配置的ApplicationContext抽象类 ClassPathXmlApplicationContext 解析应用根目录的 FileSystemXmlApplicationContext 解析文件系统目录的 2.常规的ApplicationContext GenericApplicationContext GenericXmlApplicationContext 常规的基于xml解析的ApplicationContext AnnotationConfigApplicationContext 基于注解配置的ApplicationContext GenericWebApplicationContext 常规的web应用的ApplicationContext
最新回复(0)