一篇文章彻底搞懂spring的ApplicationContext体系

本文主要介绍ApplicationContext在Spring中各个子类的作用和区别

一、ApplicationContext子类体系图

在这里插入图片描述

从图中我们可以得到两个重要信息:

  1. ApplicationContext的子类都是继承自AbstractApplicationContext
  2. AbstractApplicationContext的子类分为两类,一类是GenericApplicationContext的子类,一类是AbstractRefreshableApplicationContext的子类.

接下来我们沿着这两个特点进行分析

1.1.AbstractApplicationContext

1.1.1.作用介绍

我们先来看下源码中的注释对ApplicationContext作用的定位:

 /*Abstract implementation of the {@link org.springframework.context.ApplicationContext}
 * interface. Doesn't mandate the type of storage used for configuration; simply
 * implements common context functionality. Uses the Template Method design pattern,
 * requiring concrete subclasses to implement abstract methods.
 *
 * <p>In contrast to a plain BeanFactory, an ApplicationContext is supposed
 * to detect special beans defined in its internal bean factory:
 * Therefore, this class automatically registers
 * {@link org.springframework.beans.factory.config.BeanFactoryPostProcessor BeanFactoryPostProcessors},
 * {@link org.springframework.beans.factory.config.BeanPostProcessor BeanPostProcessors}
 * and {@link org.springframework.context.ApplicationListener ApplicationListeners}
 * which are defined as beans in the context.
 *
 * <p>A {@link org.springframework.context.MessageSource} may also be supplied
 * as a bean in the context, with the name "messageSource"; otherwise, message
 * resolution is delegated to the parent context. Furthermore, a multicaster
 * for application events can be supplied as "applicationEventMulticaster" bean
 * of type {@link org.springframework.context.event.ApplicationEventMulticaster}
 * in the context; otherwise, a default multicaster of type
 * {@link org.springframework.context.event.SimpleApplicationEventMulticaster} will be used.
 *
 * <p>Implements resource loading through extending
 * {@link org.springframework.core.io.DefaultResourceLoader}.
 * Consequently treats non-URL resource paths as class path resources
 * (supporting full class path resource names that include the package path,
 * e.g. "mypackage/myresource.dat"), unless the {@link #getResourceByPath}
 * method is overwritten in a subclass.
   */
  1. AbstractApplication是对ApplicationContext接口的一个抽象实现类,它不持有任何配置,仅仅是对公共上下文功能的实现.使用模版方法设计模式,需要子类实现其抽线方法
  2. 与BeanFactory相比,ApplicationContext的作用是检测内部Bean工厂的特殊bean的定义,因此它会有以下操作:
    1. 自动把BeanFactoryPostProcessors、BeanPostProcessors、ApplicationListeners注册成bean
    2. 在context中以bean的形式提供MessageSource,bean名称为messageSource
    3. 在context中以bean的形式提供ApplicationEventMulticaster,bean名称为applicationEventMulticaster,并提供默认实现SimpleApplicationEventMulticaster
  3. 通过继承DefaultResourceLoader来实现资源加载功能

接下来我们来看下AbstractApplicationContext具体做了哪些工作

1.1.2.AbstractApplicationContext功能

1.1.2.1.对ApplicationContext接口的实现
1.1.2.1.1.对ApplicationContext接口本身定义的实现

ApplicationContext接口定义:

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;
}

AbstractApplicationContext通过持有对应属性值来实现:

	private String id = ObjectUtils.identityToString(this);
	private String displayName = ObjectUtils.identityToString(this);
	private ApplicationContext parent;
	private long startupDate;
  1. 其中ApplicationName默认为空
  2. getAutowireCapableBeanFactory通过抽象方法getBeanFactory有子类实现,
1.1.2.1.2.对ApplicationContext父接口EnvironmentCapable的实现

AbstractApplicationContext 定义了一个ConfigurableEnvironment属性:

private ConfigurableEnvironment environment;

ConfigurableEnvironment 里面持有当前应用yml文件中所用变量信息.

使用方法:

application.yml配置:

app.name: springmvc

1.通过ConfigurableEnvironment获取:

在ApplicationContext中定义的ConfigurableEnvironment,实际的子类是StandardEnvironment.

@SpringBootApplication
public class SpringMvcApp {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SpringMvcApp.class,args);
        StandardEnvironment standardEnvironment = (StandardEnvironment) context.getEnvironment();
        String appName = standardEnvironment.getProperty("app.name");
        System.out.println("appName:"+appName);
    }
}

appName:springmvc

2.占位符获取

@Service
public class UserServiceImpl implements UserService , InitializingBean {

    @Value("${app.name}")
    private String appName;
  
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("占位符获取appName:"+appName);
    }
}
1.1.2.1.2.对ApplicationContext父接口ApplicationEventPublisher的实现
public interface ApplicationEventPublisher {

	default void publishEvent(ApplicationEvent event) {
		publishEvent((Object) event);
	}
	
	void publishEvent(Object event);

}

ApplicationEventPublisher接口是发送容器事件的接口,通过观察者模式实现,会在容器不同阶段发送不同的ApplicationEvent.

AbstractApplicationContext在refresh函数中会调用initApplicationEventMulticaster初始化一个ApplicationEventMulticaster,默认子类为:SimpleApplicationEventMulticaster,用于发送ApplicationEvent和管理当前应用中注册的ApplicationListener.

你也可以定义自己的ApplicationEventMulticaster,设置bean名称为applicationEventMulticaster,就可以替换默认的实现.

public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";

我们来看下ApplicationEventMulticaster工作原理:

在这里插入图片描述

既然ApplicationEventMulticaster是通过观察者模式来实现ApplicationEvent的广播,那么ApplicationEventMulticaster的实现中一定会持有一组观察者,即一组ApplicationListener的实现.

果然在AbstractApplicationEventMulticaster,定义了一个ListenerRetriever,而这个ListenerRetriever就持有一组ApplicationListener.

public abstract class AbstractApplicationEventMulticaster
		implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware {

	private final ListenerRetriever defaultRetriever = new ListenerRetriever(false);
  
}


private class ListenerRetriever {
  ...
		public final Set<ApplicationListener<?>> applicationListeners;
  ...
}

AbstractApplicationEventMulticaster提供了添加、删除和获取ApplicationListener的功能.这里不在粘贴AbstractApplicationEventMulticaster的源码.

我们看下SimpleApplicationEventMulticaster是如何广播ApplicationEvent事件的.

public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {

	@Nullable
	private Executor taskExecutor;

	@Nullable
	private ErrorHandler errorHandler;
	@Override
	public void multicastEvent(ApplicationEvent event) {
		multicastEvent(event, resolveDefaultEventType(event));
	}

	@Override
	public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
		for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
			Executor executor = getTaskExecutor();
			if (executor != null) {
				executor.execute(() -> invokeListener(listener, event));
			}
			else {
				invokeListener(listener, event);
			}
		}
	}
  
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
		ErrorHandler errorHandler = getErrorHandler();
		if (errorHandler != null) {
			try {
				doInvokeListener(listener, event);
			}
			catch (Throwable err) {
				errorHandler.handleError(err);
			}
		}
		else {
			doInvokeListener(listener, event);
		}
	}

	@SuppressWarnings({"unchecked", "rawtypes"})
	private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
		try {
			listener.onApplicationEvent(event);
		}
		catch (ClassCastException ex) {
			String msg = ex.getMessage();
			if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
				// Possibly a lambda-defined listener which we could not resolve the generic event type for
				// -> let's suppress the exception and just log a debug message.
				Log logger = LogFactory.getLog(getClass());
				if (logger.isDebugEnabled()) {
					logger.debug("Non-matching event type for listener: " + listener, ex);
				}
			}
			else {
				throw ex;
			}
		}
	}
	
	
	}

从multicastEvent函数可以看出,SimpleApplicationEventMulticaster在广播ApplicationEvent事件时有两种策略:

  1. 设置了线程池,则将广播ApplicationEvent的任务提交到线程池异步执行
  2. 没有设置线程池,则同步执行广播ApplicationEvent的任务
1.1.2.1.3.对ApplicationContext父接口BeanFactory、ListableBeanFactory、HierarchicalBeanFactory的实现

AbstractApplicationContext对BeanFactory、ListableBeanFactory、HierachicalBeanFactory的实现,都通过抽象方法getBeanFactory获得子类持有的ConfigurableListableBeanFactory来实现这三个BeanFactory的功能,AbstractApplicationContext充当了一个代理的角色.

1.1.2.1.4.对ApplicationContext父接口MessageSource的实现

MessageSource是spring对国际化的实现,这里不详细介绍,后面会有文章详细介绍其原理.

1.1.2.1.5.对ApplicationContext父接口ResourcePatternResolver的实现

ResourcePatternResolver提供了根据路径查找对应资源文件的功能.

public interface ResourcePatternResolver extends ResourceLoader {

	String CLASSPATH_ALL_URL_PREFIX = "classpath*:";

	Resource[] getResources(String locationPattern) throws IOException;

}

AbstractApplicationContext中不具体实现其功能,而是充当代理者的角色,具体实现有PathMatchingResourcePatternResolver完成.

PathMatchingResourcePatternResolver主要解析classpath路径下的文件

1.1.2.2.对ConfigurableApplicationContext接口的实现

AbstractApplicationContext最重要的实现.

public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {
	
  /**
  添加一个BeanFactoryPostProcessor,在内部BeanFactory执行refresh时,并bean definition使用之前被执行
  在读取上下文配置时使用.
  **/
  void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor);

  /**
  添加一个ApplicationListener,用于监听ApplicationEvent
  ***/
	void addApplicationListener(ApplicationListener<?> listener);

  /**
   添加一个特殊资源协议的解析器
  ***/
	void addProtocolResolver(ProtocolResolver resolver);

  /**
   从xml、properties、数据库中加载配置,来创建bean实例.
   这是一个启动方法,在调用这个方法后,要不一个bean都没有,要不所有的都已经实例化完成
  **/
	void refresh() throws BeansException, IllegalStateException;

  /**
  注册jvm shutdown 钩子函数
  **/
	void registerShutdownHook();

  /**
  关闭context,释放子类持有的所有资源
  ***/
	@Override
	void close();

  /**
  判断context是否启动
  ***/
	boolean isActive();

  /**
   获取内部bean工厂
  ***/
	ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;

}

ConfigurableApplicationContext的作用?

ConfigurableApplicationContext 重点在于设置应用的相关组件,而ApplicationContext接口重点在于获取配置.

下面主要看下refresh函数,该函数定义了context初始化的主要流程,其中就包括初始化容器中bean的主流程.

我们看下refresh函数做了哪些工作?

@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
    ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

prepareRefresh阶段

该阶段主要设置启动时间和启动标识,可以被子类覆盖,但覆盖逻辑里面一定要调用super.prepareRefresh();

obtainFreshBeanFactory阶段

获取子类持有的BeanFactory.

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		refreshBeanFactory();
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (logger.isDebugEnabled()) {
			logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
		}
		return beanFactory;
	}

refreshBeanFactory()是一个抽象函数,只有当前ApplicationContext是AbstractRefreshableApplicationContext的子类时才有具体逻辑,如下:

@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);
		}
	}

如果当前ApplicationContext已经持有了BeanFactory实例,那么重新销毁所有的bean,并重新加载,相当于每次返回一个新的BeanFactory实例.

prepareBeanFactory阶段

配置BeanFactory设置内置的Bean和相关配置如classloader、el表达式解析器等

postProcessBeanFactory阶段

这时Beanfactory已经初始化完成,所有的bean definition已加载,但是还未实例bean,允许AbstractApplication的子类对BeanFactory进行修改,

如注册BeanPostProcessors.

invokeBeanFactoryPostProcessors阶段

实例化并执行所有BeanFactoryPostProcessor的bean,如有设置了顺序,则按顺序执行.

在springboot应用中,在这个过程开始ConfigurationClassPostProcessor来扫描用户系统的class,并将其转化成Bean definition注册到BeanFactory中.

registerBeanPostProcessors阶段

实例化所有的BeanPostProcessor ,并注册

initMessageSource阶段

初始化国际化相关配置

initApplicationEventMulticaster阶段

设置ApplicationEvent广播控制器

onRefresh阶段

模版方法,可以用于初始化特殊的bean

registerListeners阶段

注册ApplicationListener,用于监听ApplicationEventMulticaster广播的ApplicationEvent事件

finishBeanFactoryInitialization阶段-bean生命周期开始阶段

这个阶段才开始将剩余的Bean进行初始化,用户设置的非懒加载的bean都在这阶段完成.

如@Controller、@Service、@Compenont等修饰的.

finishRefresh阶段

ApplicationContext refresh流程完成,容器初始化完成,做以下工作

  • 发送ContextRefreshedEvent事件
  • 删除Context -level 缓存,如扫描到的类信息
  • 注册LifecycleProcessor,并执行onRefresh方法
1.1.2.5.对Lifecycle接口的实现

生命周期接口,没有看到在哪里使用到.

public interface Lifecycle {


	void start();

	void stop();

	boolean isRunning();

}

1.2GenericApplicationContext和AbstractRefreshableApplicationContext对比

1.2.1.继承关系对比

先贴两张图,看下两者的继承关系:

GenericApplicationContext继承关系
在这里插入图片描述

AbstractRefreshableApplicationContext继承关系
在这里插入图片描述

从继承关系上看GenericeApplicationContext实现了BeanDefinitionRegistry接口,BeanDefinitionRegistry 有什么作用:

public interface BeanDefinitionRegistry extends AliasRegistry {

	void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException;

	void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

	BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

	boolean containsBeanDefinition(String beanName);
  
	String[] getBeanDefinitionNames();

	int getBeanDefinitionCount();

	boolean isBeanNameInUse(String beanName);

}

BeanDefinitionRegistry提供了注册Bean Definition的功能,当前其子类的实现也会持有这些Bean Definitions.

1.2.2.AbstractApplicationContext抽象方法实现对比

GenericApplicationContext

public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
...
	@Override
	protected final void refreshBeanFactory() throws IllegalStateException {
		if (!this.refreshed.compareAndSet(false, true)) {
			throw new IllegalStateException(
					"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
		}
		this.beanFactory.setSerializationId(getId());
	}
	...

}

AbstractRefreshableApplicationContext

public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {

@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);
		}
	}

	protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
			throws BeansException, IOException;
}

GenericApplicationContext和AbstractRefreshableApplicationContext在实现AbstractApplicationContext的refreshBeanFactory有区别:

  1. GenericApplicationContext 没有做任何动作,只是判断了一下当前refresh的次数,最多只能一次.
  2. AbstractRefreshableApplicationContext:每次refresh都会重新生成BeanFactory,并重新加载Bean,加载bean definitions通过loadBeanDefinitions抽象方法,尤其子类实现.

总结:

  1. GenericApplicationContext子类只会调用一次refresh过程,并且可以由其他组件向它组册Bean Definition
  2. AbstractRefreshableApplicationContext支持多次refresh,但是需要子类提供bean配置地址

二、GenericApplicationContext子类分析

我们先来看下GenericeApplicationContext有哪些子类,然后逐个介绍:

在这里插入图片描述

2.1GenericWebApplicationContext和其子类

GenericWebApplicationContext对在web环境下GenericApplicationContext实现.

有以下功能:

  1. 可以基于编程配置web相关信息,而不是传统的web.xml.
  2. web相关的配置通过WebApplicationInitializer在tomcat启动后,调用onStartup方法配置servlet/filter/listener等信息.
  3. 添加ThemeSource bean,用于web环境的主题切换

ServletWebServerApplicationContext

ServletWebServerApplicationContext是GenericWebApplicationContext的直接子类,相比于GenericWebApplicationContext,

ServletWebServerApplicationContext增加了创建、初始化一个web server的功能.

	@Override
	protected void onRefresh() {
		super.onRefresh();
		try {
			createWebServer();
		}
		catch (Throwable ex) {
			throw new ApplicationContextException("Unable to start web server", ex);
		}
	}
	
	
	private void createWebServer() {
		WebServer webServer = this.webServer;
		ServletContext servletContext = getServletContext();
		if (webServer == null && servletContext == null) {
			ServletWebServerFactory factory = getWebServerFactory();
			this.webServer = factory.getWebServer(getSelfInitializer());
		}
		else if (servletContext != null) {
			try {
				getSelfInitializer().onStartup(servletContext);
			}
			catch (ServletException ex) {
				throw new ApplicationContextException("Cannot initialize servlet context",
						ex);
			}
		}
		initPropertySources();
	}

ServletWebServerApplicationContext是可以面向开发者直接使用的一个web 类型的ApplicationContext,但是spring提供了更好的选择.

AnnotationConfigServletWebServerApplicationContext和XmlServletWebServerApplicationContext.

AnnotationConfigServletWebServerApplicationContext

该context可以根据一个配置了配置文件路径也是扫描bean的路径或包名的@Configuration类,来初始化我们的应用,完成bean的加载等.

在springboot中

@SpringBootApplication
public class SpringMvcApp {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SpringMvcApp.class,args);
        
    }
}

SpringApplication.run返回的ApplicationContext 实际就是AnnotationConfigServletWebServerApplicationContext

XmlServletWebServerApplicationContext

相比于AnnotationConfigServletWebServerApplicationContext通过注解方式配置bean的配置文件、资源文件,XmlServletWebServerApplicationContext是通过提供相应的构造函数传入文件路径或者通过load方法加载相应的资源文件.


public class XmlServletWebServerApplicationContext
		extends ServletWebServerApplicationContext {

	private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);

	public XmlServletWebServerApplicationContext() {
		this.reader.setEnvironment(this.getEnvironment());
	}

	public XmlServletWebServerApplicationContext(Resource... resources) {
		load(resources);
		refresh();
	}

	public XmlServletWebServerApplicationContext(String... resourceLocations) {
		load(resourceLocations);
		refresh();
	}
	public XmlServletWebServerApplicationContext(Class<?> relativeClass,
			String... resourceNames) {
		load(relativeClass, resourceNames);
		refresh();
	}

	public void setValidating(boolean validating) {
		this.reader.setValidating(validating);
	}


	public final void load(Resource... resources) {
		this.reader.loadBeanDefinitions(resources);
	}

	public final void load(String... resourceLocations) {
		this.reader.loadBeanDefinitions(resourceLocations);
	}


	public final void load(Class<?> relativeClass, String... resourceNames) {
		Resource[] resources = new Resource[resourceNames.length];
		for (int i = 0; i < resourceNames.length; i++) {
			resources[i] = new ClassPathResource(resourceNames[i], relativeClass);
		}
		this.reader.loadBeanDefinitions(resources);
	}

}

加载资源的方式:

  • 构造函数传入
  • 调用load方法

2.2.AnnotationConfigApplicationContext和GenericXmlApplicationContext

AnnotationConfigApplicationContext/GenericXmlApplicationContext同AnnotationConfigServletWebServerApplicationContext/XmlServletWebServerApplicationContext类似

  • AnnotationConfigApplicationContext是通过@Configuration类来加载资源文件,初始化当前ApplicationContext的.
  • GenericXmlApplicationContext通过特定文件加载资源

不同的是:AnnotationConfigApplicationContextAnnotationConfigApplicationContext/GenericXmlApplicationContext是非web的ApplicationContext,AnnotationConfigServletWebServerApplicationContext/XmlServletWebServerApplicationContext是支持web服务的context,可以提供对外的web服务.

假如你要写一个tcp服务,可以用这两者中的一个作为你管理bean的容器,只不过你需要自己在AbstractApplicationContext.refresh执行的某一个步骤或其他时机,完成自己的端口监听等.

或者,当前你的服务不需要对外提供服务,你也可以选择该这两个context.

2.3.StaticApplicationContext和其子类

StaticApplicationContext和StaticWebApplicationContext不会扫描任何文件,而是通过相应的方法直接注册bean,一般用于测试.

2.4.GenericGroovyApplicationContext

GenericGroovyApplicationContext提供了spring对Groovy的支持,可以加载Groovy bean definition,并完成bean的注册.

2.5.GenericReactiveWebApplicationContext和其子类

GenericReactiveWebApplicationContext和ReactiveWebServerApplicationContext同GenericWebApplicationContext和ServletWebServerApplicationContext功能类似,只不过是对reactive环境的支持.

  • GenericReactiveWebApplicationContext不会启动一个web server,资源路径使用相对路径
  • ReactiveWebServerApplicationContext启动一个webserver

二、AbstractRefreshableApplicationContext子类分析

AbstractRefreshableApplicationContext体系基本上和GenericApplicationContext类似,它们最本质的区别就是:

在refreshBeanFactory阶段AbstractRefreshableApplicationContext体系的ApplicationContext会返回一个新的BeanFactory,并重新加载bean.

而GenericApplicationContext体系的ApplicationContext会一直使用refresh前创建的BeanFactory.

AbstractRefreshableApplicationContext的好处是可以执行多次refresh.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序猿老徐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值