重新认识 Spring IOC (3)

我们看到 initWebApplicationContext() 正是容器初始化的方法,我们继续跟进,我们现在是看容器初始化,其他暂时过掉,后面讲springmvc时在系统讲解

/** * 初始化web容器 WebApplicationContext * Initialize and publish the WebApplicationContext for this servlet. * <p>Delegates to {@link #createWebApplicationContext} for actual creation * of the context. Can be overridden in subclasses. * @return the WebApplicationContext instance * @see #FrameworkServlet(WebApplicationContext) * @see #setContextClass * @see #setContextConfigLocation */ protected WebApplicationContext initWebApplicationContext() { //从ServletContext根容器中获取父容器 WebApplicationContext WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); //声明子容器 WebApplicationContext wac = null; //构建父子容器的关系,这里判断当前容器是否有, // 若存在则作为子容器来给他设置父容器rootcontext if (this.webApplicationContext != null) { // A context instance was injected at construction time -> use it wac = this.webApplicationContext; if (wac instanceof ConfigurableWebApplicationContext) { ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac; if (!cwac.isActive()) { // The context has not yet been refreshed -> provide services such as // setting the parent context, setting the application context id, etc if (cwac.getParent() == null) { // The context instance was injected without an explicit parent -> set // the root application context (if any; may be null) as the parent cwac.setParent(rootContext); } configureAndRefreshWebApplicationContext(cwac); } } } //判断子容器是否有引用,在ServletContext根容器中寻找,找到则赋值 if (wac == null) { // No context instance was injected at construction time -> see if one // has been registered in the servlet context. If one exists, it is assumed // that the parent context (if any) has already been set and that the // user has performed any initialization such as setting the context id wac = findWebApplicationContext(); } //若上面寻找也没找到,则这里进行容器的赋值 构建一个容器,但是这个容器并没有初始化 只是建立了引用 if (wac == null) { // No context instance is defined for this servlet -> create a local one wac = createWebApplicationContext(rootContext); } //这里触发onRefresh方法进行容器真真初始化 if (!this.refreshEventReceived) { // Either the context is not a ConfigurableApplicationContext with refresh // support or the context injected at construction time had already been // refreshed -> trigger initial onRefresh manually here. synchronized (this.onRefreshMonitor) { onRefresh(wac); } } if (this.publishContext) { // Publish the context as a servlet context attribute. String attrName = getServletContextAttributeName(); getServletContext().setAttribute(attrName, wac); } return wac; }

我们看到真真初始化容器的方法 onRefresh() 方法, 跟进找到 DispatcherServlet 中的实现类,其中又调用了 initStrategies() 方法,继续进入

/** * This implementation calls {@link #initStrategies}. */ @Override protected void onRefresh(ApplicationContext context) { initStrategies(context); } /** * 初始化容器,进行springmvc的9大组件初始化 * Initialize the strategy objects that this servlet uses. * <p>May be overridden in subclasses in order to initialize further strategy objects. */ protected void initStrategies(ApplicationContext context) { //多文件上传组件 initMultipartResolver(context); //国际化组件,也就是本地语言环境 initLocaleResolver(context); //初始化主题模板处理器 initThemeResolver(context); //初始化HandMapping映射 initHandlerMappings(context); //初始化HandlerAdapters参数适配器 initHandlerAdapters(context); //初始化一场拦截组件 initHandlerExceptionResolvers(context); //初始化视图预处理解析器, initRequestToViewNameTranslator(context); //初始化视图解析器 initViewResolvers(context); //初始化FlashMap initFlashMapManager(context); } IOC容器初始化

IOC容器的初始化有多种方式,可以是配置文件也可以为 Javaconfig 的方式,常见的如 ClassPathXmlApplicationContext

ioc类图.png

IOC中主要过程可以概述为_定位_、加载、注册 三个基本过程,我们常见的容器都是 ApplicationContext , ResourceLoader 是所有资源加载的基类,我们可以发现所有的IOC容器都是继承了 BeanFactory ,这也说明了所有的容器本质上都是一个bean工厂

我们可以通过下面的代码获取容器

ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(CONTEXT_WILDCARD);

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wspjpz.html