本系列文章将逐一介绍,Spring容器创建到容器刷新完成每个过程。
Spring容器继承结构图
第一步,new容器实例
ApplicationContext factory = new ClassPathXmlApplicationContext("classpath:application.xml");
容器构造器
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
// 配置路径转为String数组,刷新容器,父容器为null
this(new String[] {configLocation}, true, null);
}
最终调用的构造器
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
// 检测解析一下配置文件,保存配置文件路径在 this.configLocations 属性中
setConfigLocations(configLocations);
if (refresh) {
// 容器启动的关键步骤,刷新容器
refresh();
}
}
refresh()
refresh()方法中完成Spring容器的初始化,事件的派发,bean生命周期管理。是容器创建最重要的一个步骤。方法的实现在AbstractApplicationContext中,这个系列将逐个方法的介绍。
refresh方法概览:可直接跳过。
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();
refresh()中的第一个方法调用,prepareRefresh,做刷新容器前的准备工作。
废话不说,直接看源码。
protected void prepareRefresh() {
// 设置容器启动时间
this.startupDate = System.currentTimeMillis();
// 设置容器激活标记
this.closed.set(false);
this.active.set(true);
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
// 留给子类
initPropertySources();
// 获取运行环境,验证属性
getEnvironment().validateRequiredProperties();
// 创建一个链表存放容器早期事件
this.earlyApplicationEvents = new LinkedHashSet<>();
}
getEnvironment()
getEnvironment最终获取一个StandardEnvironment。
@Override
public ConfigurableEnvironment getEnvironment() {
if (this.environment == null) {
this.environment = createEnvironment();
}
return this.environment;
}
protected ConfigurableEnvironment createEnvironment() {
return new StandardEnvironment();
}
StandardEnvironment类型结构
Environment接口代表当前应用所处环境,springBean支持和一个Profile绑定,方便与测试环境开发环境切换。
PropertyResolver中的Property指程序运行时的参数,如系统参数,JVM参数等
StandardEnvironment构造器中做了些什么
// 在构造器中,初始化一些定制属性
public AbstractEnvironment() {
// 方法在StandardEnvironment中实现
// this.propertySources是一个MutablePropertySources用于保存属性
customizePropertySources(this.propertySources);
if (logger.isDebugEnabled()) {
logger.debug("Initialized " + getClass().getSimpleName() + " with PropertySources " + this.propertySources);
}
}
在StandardEnvironment中实现了定制属性方法
@Override
protected void customizePropertySources(MutablePropertySources propertySources) {
// 添加系统属性
propertySources.addLast(new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
// 添加系统环境
propertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
}
validateRequiredProperties 验证属性
getEnvironment()得到一个StandardEnvironment,然后调用它父类的的ValidateRequiredProperties进行属性验证。
@Override
public void validateRequiredProperties() throws MissingRequiredPropertiesException {
this.propertyResolver.validateRequiredProperties();
}
// AbstractEnvironment的解析器
private final ConfigurablePropertyResolver propertyResolver =
new PropertySourcesPropertyResolver(this.propertySources);
// 在StandarEnvironment父类AbstractEnvironment中
@Override
public void validateRequiredProperties() throws MissingRequiredPropertiesException {
this.propertyResolver.validateRequiredProperties();
}
@Override
public void validateRequiredProperties() {
MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException();
// 验证是否缺少属性值
for (String key : this.requiredProperties) {
if (this.getProperty(key) == null) {
ex.addMissingRequiredProperty(key);
}
}
if (!ex.getMissingRequiredProperties().isEmpty()) {
throw ex;
}
}