注:本系列源码分析基于spring 5.2.2.RELEASE,本文的分析基于 annotation 注解方式,gitee仓库链接:gitee.com/funcy/sprin….
1. ApplicationContext 简介
我们在启动spring容器时,一般像这样启动:
ApplicationContext context = new AnnotationConfigApplicationContext(Main.class);
或这样:
ApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(MvcConfig.class);
context.refresh();
这里的 AnnotationConfigApplicationContext 与 AnnotationConfigWebApplicationContext 都是ApplicationContext,最终进行会调用AbstractApplicationContext#refresh方法启动spring容器。
ApplicationContext 翻译为 spring应用上下文,从这个类里可以获取spring运行期间的各种信息,如BeanFactory、Environment等,是spring中至关重要的一个类。
ApplicationContext 继承的接口如下:
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory,
HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher,
ResourcePatternResolver {
...
}
从这里可以看到,ApplicationContext 本身也是其他接口的子接口,这些接口的功能如下:
EnvironmentCapable:提供了环境配置功能,applicationContext实现中会有一个Environment类型的成员变量,可以通过EnvironmentCapable#getEnvironment()方法取得ListableBeanFactory:BeanFactory的子接口,提供了列举BeanFactory中所有bean的方法HierarchicalBeanFactory:BeanFactory的子接口,提供了BeanFactory类似继承的能力(可以获取父BeanFactory)MessageSource:指定消息来源,可以用来实现国际化操作ApplicationEventPublisher:事件发布器,用其提供的publishEvent(...)方法来发布事件ResourcePatternResolver:资源解析器,提供了获取资源(Resource)的方法:getResources(...)
我们来看看ApplicationContext自身提供的方法:
可以看到,它自身的方法并不多。
2. ApplicationContext 继承结构
在ApplicationContext家族中,ApplicationContext主要分为两大派系,他们及其代表如下:
- 非web类型的
ApplicationContext:处理普通java应用的ApplicationContext,代表类为AnnotationConfigApplicationContext - web类型的
ApplicationContext:处理 web 应用的ApplicationContext,代表类为AnnotationConfigWebApplicationContext(这里只考虑servlet类型的web,不考虑reactive的web)
我们再来看看AnnotationConfigApplicationContext的继承结构:
我们再来看看AnnotationConfigWebApplicationContext的继承结构:
3. 在bean中获取ApplicationContext
在 spring bean 中获取ApplicationContext,可以通过 ApplicationContextAware 接口来处理:
@Component
public class TestBean implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
// 其他操作
}
继承ApplicationContextAware后,ApplicationContextAwareProcessor会在初始化完成后调用setApplicationContext(xxx)方法,这样我们只需要在TestBean中维护一个成员变量,对applicationContext保存即可。
4. ApplicationContextAwareProcessor
ApplicationContextAwareProcessor是一个 BeanPostProcessor,我们主要关注 ApplicationContextAwareProcessor#postProcessBeforeInitialization方法,代表如下:
@Override
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
/**
* applicationContext 是 Environment、ResourceLoader、
* ApplicationEventPublisher、MessageSource 等的子类,这些类的aware接口的调用,都可以
* 通过 applicationContext 参数进行
*/
if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
return bean;
}
AccessControlContext acc = null;
if (System.getSecurityManager() != null) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareInterfaces(bean);
return null;
}, acc);
}
else {
invokeAwareInterfaces(bean);
}
return bean;
}
/**
* 调用 Aware 接口的方法
* 除了EmbeddedValueResolverAware外,其余的传入参数都是 this.applicationContext
*/
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
// 注意embeddedValueResolver的获取操作如下:
// new EmbeddedValueResolver(applicationContext.getBeanFactory());
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(
this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
// 装配 实现了ApplicationContextAware的类的 applicationContext
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
这个方法还是比较简单的,就是判断bean类型,然后转换、调用方法。
5. ApplicationContext 与 BeanFactory 的关系
最后我们再来讨论下ApplicationContext 与 BeanFactory 两者的关系。本文一开始就说明了ApplicationContext继承了BeanFactory的接口,因为这两者是继承关系。不过,除了继承关系外,他们还是组合关系,ApplicationContext 持有 BeanFactory 的对象,直接看代码:
对于AnnotationConfigApplicationContext,beanFactory赋值代码如下:
public class GenericApplicationContext extends AbstractApplicationContext
implements BeanDefinitionRegistry {
// 这就是持有的 beanFactory 对象
private final DefaultListableBeanFactory beanFactory;
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
return this.beanFactory;
}
...
}
对于 AnnotationConfigWebApplicationContext,beanFactory赋值代码如下:
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
// 这就是持有的 beanFactory 对象
@Nullable
private DefaultListableBeanFactory beanFactory;
@Override
protected final void refreshBeanFactory() throws BeansException {
// 判断当前ApplicationContext是否存在BeanFactory,如果存在的话就销毁所有 Bean,关闭 BeanFactory
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 初始化DefaultListableBeanFactory,看下面的创建方法
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
// 设置 BeanFactory 的两个配置属性:是否允许 Bean 覆盖、是否允许循环引用
customizeBeanFactory(beanFactory);
// 加载 Bean 到 BeanFactory 中
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
...
}
}
// 创建 beanFactory
protected DefaultListableBeanFactory createBeanFactory() {
// 指定父beanFactory
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
// 获取 beanFactory
@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
synchronized (this.beanFactoryMonitor) {
if (this.beanFactory == null) {
...
}
return this.beanFactory;
}
}
...
}
BeanFactory的相关方法实现如下:
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
...
@Override
public <T> T getBean(Class<T> requiredType) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(requiredType);
}
@Override
public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(requiredType, args);
}
...
}
这些方法在实现时,都是调用getBeanFactory()获取到BeanFactory对象,然后直接调用BeanFactory的方法,getBeanFactory()调用的就是GenericApplicationContext或AnnotationConfigWebApplicationContext的getBeanFactory()方法。
关于ApplicationContext的内容就介绍到这里了。
本文原文链接:my.oschina.net/funcy/blog/… ,限于作者个人水平,文中难免有错误之处,欢迎指正!原创不易,商业转载请联系作者获得授权,非商业转载请注明出处。
本系列的其他文章