最近在SVN上下载了Spring3.0的源码学习. 先介绍个人到现在对于Spring中IOC的认识吧.欢迎大家一起讨论,呵呵,别拍砖.
Spring的IOC的实现分为 1. 资源(Resource)定位 2.资源(Resource)载入 3.资源的解析 4.Bean的注册 5.getBean时对象依赖关系的注入.以最通常用的web项目开始
Spring通过web容器启动是通过org.springframework.web.context.ContextLoaderListener来实现的,其代码如下:
其对ContextLoader的继承及对ServletContextListener的实现使用了适配器模式.
现在看看contextLoader中的initWebApplicationContext方法.
//监听器的初始化方法.对web应用的上下文进行初始化 public void contextInitialized(ServletContextEvent event) { this.contextLoader = createContextLoader(); if (this.contextLoader == null) { this.contextLoader = this; } this.contextLoader.initWebApplicationContext (event.getServletContext()); }
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) { if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) { throw new IllegalStateException( "Cannot initialize context because there is already a root application context present - " + "check whether you have multiple ContextLoader* definitions in your web.xml!"); } Log logger = LogFactory.getLog(ContextLoader.class); servletContext.log("Initializing Spring root WebApplicationContext"); if (logger.isInfoEnabled()) { logger.info("Root WebApplicationContext: initialization started"); } long startTime = System.currentTimeMillis(); try { // Determine parent for root web application context, if any. ApplicationContext parent = loadParentContext(servletContext); // Store context in local instance variable, to guarantee that // it is available on ServletContext shutdown. this.context = createWebApplicationContext(servletContext, parent); servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context); ClassLoader ccl = Thread.currentThread().getContextClassLoader(); if (ccl == ContextLoader.class.getClassLoader()) { currentContext = this.context; } else if (ccl != null) { currentContextPerThread.put(ccl, this.context); } if (logger.isDebugEnabled()) { logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" + WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]"); } if (logger.isInfoEnabled()) { long elapsedTime = System.currentTimeMillis() - startTime; logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms"); } return this.context; }//异常略...
}
对容器的初始化的过程主要是通过 this.context = createWebApplicationContext(servletContext, parent);
这句完成的..进入createWebApplicationContext方法
protected WebApplicationContext createWebApplicationContext(ServletContext sc, ApplicationContext parent) { //得到确定的class对象.determineContextClass中首先在web.xml中查询是否有配置contextclass的上下文. //如果有配置,则根据所配置的对象得到其class对象.否则通过在ContextLoader.properties的 //org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext //得到XmlWebApplicationContext的class对象 Class<?> contextClass = determineContextClass(sc); if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) { throw new ApplicationContextException("Custom context class [" + contextClass.getName() + "] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]"); } //ConfigurableWebApplicationContext为接口. //通过反射将对象实例化.如果web.xml中未配置contextclass的话,实际上是XmlWebApplicationContext对象 ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass); // Assign the best possible id value. if (sc.getMajorVersion() == 2 && sc.getMinorVersion() < 5) { // Servlet <= 2.4: resort to name specified in web.xml, if any. String servletContextName = sc.getServletContextName(); wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(servletContextName)); } else { // Servlet 2.5's getContextPath available! try { String contextPath = (String) ServletContext.class.getMethod("getContextPath").invoke(sc); wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(contextPath)); } catch (Exception ex) { throw new IllegalStateException("Failed to invoke Servlet 2.5 getContextPath method", ex); } } wac.setParent(parent); wac.setServletContext(sc); wac.setConfigLocation(sc.getInitParameter(CONFIG_LOCATION_PARAM)); customizeContext(sc, wac); //容器初始化的入口 wac.refresh(); return wac; }