日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Web IOC 容器初体验

發布時間:2024/4/13 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Web IOC 容器初体验 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

我們還是從大家最熟悉的DispatcherServlet 開始,我們最先想到的還是DispatcherServlet 的init()方法。我們發現在DispatherServlet 中并沒有找到init()方法。但是經過探索,往上追索在其父類HttpServletBean 中找到了我們想要的init()方法,如下:

/*** Map config parameters onto bean properties of this servlet, and* invoke subclass initialization.* @throws ServletException if bean properties are invalid (or required* properties are missing), or if subclass initialization fails.*/ @Override public final void init() throws ServletException {if (logger.isDebugEnabled()) {logger.debug("Initializing servlet '" + getServletName() + "'");}// Set bean properties from init parameters.PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);if (!pvs.isEmpty()) {try {//定位資源BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);//加載配置信息ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));initBeanWrapper(bw);bw.setPropertyValues(pvs, true);}catch (BeansException ex) {if (logger.isErrorEnabled()) {logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);}throw ex;}}// Let subclasses do whatever initialization they like.initServletBean();if (logger.isDebugEnabled()) {logger.debug("Servlet '" + getServletName() + "' configured successfully");} }

在init()方法中,真正完成初始化容器動作的邏輯其實在initServletBean()方法中,我們繼續跟進initServletBean()中的代碼在FrameworkServlet 類中:

/*** Overridden method of {@link HttpServletBean}, invoked after any bean properties* have been set. Creates this servlet's WebApplicationContext.*/ @Override protected final void initServletBean() throws ServletException {getServletContext().log("Initializing Spring FrameworkServlet '" + getServletName() + "'");if (this.logger.isInfoEnabled()) {this.logger.info("FrameworkServlet '" + getServletName() + "': initialization started");}long startTime = System.currentTimeMillis();try {this.webApplicationContext = initWebApplicationContext();initFrameworkServlet();}catch (ServletException ex) {this.logger.error("Context initialization failed", ex);throw ex;}catch (RuntimeException ex) {this.logger.error("Context initialization failed", ex);throw ex;}if (this.logger.isInfoEnabled()) {long elapsedTime = System.currentTimeMillis() - startTime;this.logger.info("FrameworkServlet '" + getServletName() + "': initialization completed in " +elapsedTime + " ms");} }

在上面的代碼中終于看到了我們似曾相識的代碼initWebAppplicationContext(),繼續跟進:

/*** 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中獲得父容器WebAppliationContextWebApplicationContext rootContext =WebApplicationContextUtils.getWebApplicationContext(getServletContext());//聲明子容器WebApplicationContext wac = null;//建立父、子容器之間的關聯關系if (this.webApplicationContext != null) {// A context instance was injected at construction time -> use itwac = 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, etcif (cwac.getParent() == null) {// The context instance was injected without an explicit parent -> set// the root application context (if any; may be null) as the parentcwac.setParent(rootContext);}//這個方法里面調用了AbatractApplication的refresh()方法//模板方法,規定IOC初始化基本流程configureAndRefreshWebApplicationContext(cwac);}}}//先去ServletContext中查找Web容器的引用是否存在,并創建好默認的空IOC容器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 idwac = findWebApplicationContext();}//給上一步創建好的IOC容器賦值if (wac == null) {// No context instance is defined for this servlet -> create a local onewac = 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.onRefresh(wac);}if (this.publishContext) {// Publish the context as a servlet context attribute.String attrName = getServletContextAttributeName();getServletContext().setAttribute(attrName, wac);if (this.logger.isDebugEnabled()) {this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() +"' as ServletContext attribute with name [" + attrName + "]");}}return wac; }/*** Retrieve a {@code WebApplicationContext} from the {@code ServletContext}* attribute with the {@link #setContextAttribute configured name}. The* {@code WebApplicationContext} must have already been loaded and stored in the* {@code ServletContext} before this servlet gets initialized (or invoked).* <p>Subclasses may override this method to provide a different* {@code WebApplicationContext} retrieval strategy.* @return the WebApplicationContext for this servlet, or {@code null} if not found* @see #getContextAttribute()*/ @Nullable protected WebApplicationContext findWebApplicationContext() {String attrName = getContextAttribute();if (attrName == null) {return null;}WebApplicationContext wac =WebApplicationContextUtils.getWebApplicationContext(getServletContext(), attrName);if (wac == null) {throw new IllegalStateException("No WebApplicationContext found: initializer not registered?");}return wac; }/*** Instantiate the WebApplicationContext for this servlet, either a default* {@link org.springframework.web.context.support.XmlWebApplicationContext}* or a {@link #setContextClass custom context class}, if set.* <p>This implementation expects custom contexts to implement the* {@link org.springframework.web.context.ConfigurableWebApplicationContext}* interface. Can be overridden in subclasses.* <p>Do not forget to register this servlet instance as application listener on the* created context (for triggering its {@link #onRefresh callback}, and to call* {@link org.springframework.context.ConfigurableApplicationContext#refresh()}* before returning the context instance.* @param parent the parent ApplicationContext to use, or {@code null} if none* @return the WebApplicationContext for this servlet* @see org.springframework.web.context.support.XmlWebApplicationContext*/ protected WebApplicationContext createWebApplicationContext(@Nullable ApplicationContext parent) {Class<?> contextClass = getContextClass();if (this.logger.isDebugEnabled()) {this.logger.debug("Servlet with name '" + getServletName() +"' will try to create custom WebApplicationContext context of class '" +contextClass.getName() + "'" + ", using parent context [" + parent + "]");}if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {throw new ApplicationContextException("Fatal initialization error in servlet with name '" + getServletName() +"': custom WebApplicationContext class [" + contextClass.getName() +"] is not of type ConfigurableWebApplicationContext");}ConfigurableWebApplicationContext wac =(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);wac.setEnvironment(getEnvironment());wac.setParent(parent);String configLocation = getContextConfigLocation();if (configLocation != null) {wac.setConfigLocation(configLocation);}configureAndRefreshWebApplicationContext(wac);return wac; }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 informationif (this.contextId != null) {wac.setId(this.contextId);}else {// Generate default id...wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +ObjectUtils.getDisplayString(getServletContext().getContextPath()) + '/' + getServletName());}}wac.setServletContext(getServletContext());wac.setServletConfig(getServletConfig());wac.setNamespace(getNamespace());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 #refreshConfigurableEnvironment env = wac.getEnvironment();if (env instanceof ConfigurableWebEnvironment) {((ConfigurableWebEnvironment) env).initPropertySources(getServletContext(), getServletConfig());}postProcessWebApplicationContext(wac);applyInitializers(wac);wac.refresh(); }

從上面的代碼中可以看出,在configAndRefreshWebApplicationContext()方法中,調用refresh()方法,這個是真正啟動IOC 容器的入口,后面會詳細介紹。IOC 容器初始化以后,最后調用了DispatcherServlet 的onRefresh()方法,在onRefresh()方法中又是直接調用initStrategies()方法初始化SpringMVC 的九大組件:

/*** This implementation calls {@link #initStrategies}.*/ @Override protected void onRefresh(ApplicationContext context) {initStrategies(context); }/*** 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);//handlerMappinginitHandlerMappings(context);//初始化參數適配器initHandlerAdapters(context);//初始化異常攔截器initHandlerExceptionResolvers(context);//初始化視圖預處理器initRequestToViewNameTranslator(context);//初始化視圖轉換器initViewResolvers(context);//initFlashMapManager(context); }

?

?

?

?

總結

以上是生活随笔為你收集整理的Web IOC 容器初体验的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。