在Spring配置Servlet标签一文中介绍了Servlet的调用以及初始化过程,在一系列的初始化过程init中加载bean的模式都是先从bean工厂得到,如果没有那么就加载Spring属性文件DispatcherServlet.properties中默认的,那么在bean工厂中的bean是什么时候设置进工厂的,很简单,往下看。
先贴上继承关系图,好说话。
在FrameworkServlet类中有方法代码
protected final void initServletBean() throws ServletException {
………………
protected final void initServletBean() throws ServletException {
………………
protected WebApplicationContext initWebApplicationContext() {
// A context instance was injected at construction time -> use it
//一个context在初始化的时候被注入
wac = this.webApplicationContext;
if (wac instanceof ConfigurableWebApplicationContext) {
………………
configureAndRefreshWebApplicationContext(cwac);
………………
////等于空,加载配置文件然后刷新
if (wac == null) {
// No context instance is defined for this servlet ->
//就是说下面的代码是一定会初始化一个的,并且加载配置文件
wac = createWebApplicationContext(rootContext);
………………
下面看createWebApplicationContext()中的代码。
………………
//用反射实例化一个
ConfigurableWebApplicationContext wac =
(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
wac.setParent(parent);
//重新设置配置文件路径,然后会刷新。在listener中其实已经设置一次了,那时候已经刷新路径了加载bean了
//相当于每次该配置都要重新启动工程
wac.setConfigLocation(getContextConfigLocation());//参数配置的xml路径
configureAndRefreshWebApplicationContext(wac);
………………
注意上面的代码wac.setConfigLocation(getContextConfigLocation());
这回加载你的配置文件,一般都是类似xxx-servlet.xml的文件,在文件中你既可以用传统过的标签定义bean,也可以简单的声明几行代码告诉Spring用的是注解的方式。
通过上面的代码,很自然的我们转到configureAndRefreshWebApplicationContext方法。关键代码如下:
wac.setServletContext(getServletContext());
wac.setServletConfig(getServletConfig());
wac.setNamespace(getNamespace());
//添加监听器,org.springframework.context.event.SourceFilteringListener
wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener()));
postProcessWebApplicationContext(wac);
applyInitializers(wac);
wac.refresh();
好了,终于见到这行代码了wac.refresh();
,为什么这么说那,因为这行代码就是WebApplicationContext的更新过程,这个更新过程的后台有一系列的复杂的但是很有调理的bean的装配、加载以及部分bean的初始化过程。
详细的介绍在《Spring IOC-WebApplicationContext刷新》