上一次,我们在
Spring原码解析之SpringMVC(DispatcherServlet)初始化流程
中留下了一个方法还没有探究,如图:
这一次我们将会探究一下 configureAndRefreshWebApplicationContext() 这个方法!
FrameworkServlet.java
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) {
if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
// The application context id is still set to its original default value
// -> assign a more useful id based on available information
if (this.contextId != null) {
wac.setId(this.contextId);
}
else {
// Generate default id...
//设置容器的默认id
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
ObjectUtils.getDisplayString(getServletContext().getContextPath()) + '/' + getServletName());
}
}
//设置容器的一些初始化配置 不是我们的关乎点
wac.setServletContext(getServletContext());
wac.setServletConfig(getServletConfig());
wac.setNamespace(getNamespace());
//这是一个监听器,当发送请求时会调用,只需要实现ApplicationListener接口并注入给容器
wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener()));
// The wac environment's #initPropertySources will be called in any case when the context
// is refreshed; do it eagerly here to ensure servlet property sources are in place for
// use in any post-processing or initialization that occurs below prior to #refresh
ConfigurableEnvironment env = wac.getEnvironment();
if (env instanceof ConfigurableWebEnvironment) {
((ConfigurableWebEnvironment) env).initPropertySources(getServletContext(), getServletConfig());
}
//什么也没干 。。。。。。。
postProcessWebApplicationContext(wac);
//同样 也没干什么 。。。。。。
applyInitializers(wac);
//主要是这个方法 这个方法就在下面
wac.refresh();
}
----------------------
public void refresh() throws BeansException, IllegalStateException {
Object var1 = this.startupShutdownMonitor;
synchronized(this.startupShutdownMonitor) {
this.prepareRefresh();
//创建bean工厂 通过obtainFreshBeanFactory获取bean
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
//走完上面那一步已经拿到了文件里的bean了但是只是以读取文件的方式拿到名称
this.prepareBeanFactory(beanFactory);
//通过反射等方式 代理的方式真正的创建bean并放入bean工厂中
//这里先不做深入 我将会在后面研究ioc容器创建时分析
//可以参考我的IOC容器创建过程的博客
try {
//后置处理器
this.postProcessBeanFactory(beanFactory);
//反射调用后置处理器
this.invokeBeanFactoryPostProcessors(beanFactory);
//注册bean的后置处理器
this.registerBeanPostProcessors(beanFactory);
//初始化MessageSource
this.initMessageSource();
//初始化分发器
this.initApplicationEventMulticaster();
//模板
this.onRefresh();
//注册ApplicationListener
this.registerListeners();
//核心逻辑
this.finishBeanFactoryInitialization(beanFactory);
//完成创建 发布事件
this.finishRefresh();
} catch (BeansException var9) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
}
this.destroyBeans();
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}
}
}
Spring的原码其实很多都是使用一种模式:责任链模式
慕课网有免费课程:https://www.imooc.com/learn/257
然后是关于反射和IO的知识,慕课网也有,分享给大家:https://www.imooc.com/u/321949/courses?sort=publish
不了解JAVA注解的,这里也有课程:https://www.imooc.com/learn/456
想要更了解Spring原码的,最好先了解这些。。。。。。。。。。