AbstractApplicationContext的refresh()方法中的上下文准备方法prepareRefresh()做了那些事情?
- 记录容器的开始时间
- 设置容器的关闭状态为false
- 设置容器的激活状态为true
- 初始化系统变量值在上下文环境中
- 校验上下文环境中必须的环境值
- 初始化早期的earlyApplicationListeners监听器
- 初始化早期的earlyApplicationEvents事件
protected void prepareRefresh() {
// Switch to active.
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
}
else {
logger.debug("Refreshing " + getDisplayName());
}
}
// Initialize any placeholder property sources in the context environment.
initPropertySources();
// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
// Store pre-refresh ApplicationListeners...
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>();
}
下面选取其中几个重要点说一下。
1.初始化系统变量值在上下文环境中
// Initialize any placeholder property sources in the context environment.
initPropertySources();
protected void initPropertySources() {
// For subclasses: do nothing by default.
}
这个方法是抽象类AbstractApplicationContext留给之类实现的方法,我们可以参考 WebApplicationContextUtils.initServletPropertySources(),它去初始化了一写sevlet的环境变量参数值。
这些值可以参考servlet中的web.xml配置,这里和之前说的初始化系统环境变量模式是一样的。
MyServlet com.web.MyServlet driver com.mysql.jdbc.Driver url jdbc:mysql://localhost:3306/mysql
public static void initServletPropertySources(MutablePropertySources sources, @Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {
Assert.notNull(sources, "'propertySources' must not be null");
String name = "servletContextInitParams";
if (servletContext != null && sources.get(name) instanceof StubPropertySource) {
sources.replace(name, new ServletContextPropertySource(name, servletContext));
}
name = "servletConfigInitParams";
if (servletConfig != null && sources.get(name) instanceof StubPropertySource) {
sources.replace(name, new ServletConfigPropertySource(name, servletConfig));
}
}
2.校验环境变量中的必须值
getEnvironment().validateRequiredProperties();
如何设置必须校验?我这里继承了ClassPathXmlApplicationContext重新了initPropertySources方法,设置了必须校验的值。
public class App extends ClassPathXmlApplicationContext{
public static void main(String[] args) {
App ctx = new App("spring.xml");
}
public App(String locatio) {
super(locatio);
}
@Override
protected void initPropertySources() {
getEnvironment().setRequiredProperties("os.name.test");
}
}
os.name.test是不存在的,启动时候会报错。
os.name这里是可以正常启动的。
这里我们可以自己扩展,去设置一些自己系统启动必须设置校验的值,保证系统启动的安全。



