| # GenericServlet中初始化方法如下 |
| public void init(ServletConfig config) throws ServletException { |
| this.config = config; |
| this.init(); |
| } |
| |
| # HttpServlet类中没有重写初始化方法 |
| |
| # 查看HttpServletBean类中的初始化方法,调用了initServletBean方法 |
| @Override |
| public final void init() throws ServletException { |
| |
| |
| 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; |
| } |
| } |
| |
| |
| initServletBean(); |
| } |
| |
| # 查看initServletBean方法 |
| protected void initServletBean() throws ServletException { |
| } |
| |
| # 查看FrameworkServlet中的initServletBean方法,该类中的initServletBean方法重写的是HttpServletBean中的initServletBean |
| @Override |
| protected final void initServletBean() throws ServletException { |
| getServletContext().log("Initializing Spring " + getClass().getSimpleName() + " '" + getServletName() + "'"); |
| if (logger.isInfoEnabled()) { |
| logger.info("Initializing Servlet '" + getServletName() + "'"); |
| } |
| long startTime = System.currentTimeMillis(); |
| |
| try { |
| this.webApplicationContext = initWebApplicationContext(); |
| initFrameworkServlet(); |
| } |
| catch (ServletException | RuntimeException ex) { |
| logger.error("Context initialization failed", ex); |
| throw ex; |
| } |
| |
| if (logger.isDebugEnabled()) { |
| String value = this.enableLoggingRequestDetails ? |
| "shown which may lead to unsafe logging of potentially sensitive data" : |
| "masked to prevent unsafe logging of potentially sensitive data"; |
| logger.debug("enableLoggingRequestDetails='" + this.enableLoggingRequestDetails + |
| "': request parameters and headers will be " + value); |
| } |
| |
| if (logger.isInfoEnabled()) { |
| logger.info("Completed initialization in " + (System.currentTimeMillis() - startTime) + " ms"); |
| } |
| } |
| |
| # 在initServletBean方法中执行如下初始化webApplicationContext |
| try { |
| this.webApplicationContext = initWebApplicationContext(); |
| initFrameworkServlet(); |
| } |
| |
| # 查看initWebApplicationContext方法,通过getWebApplicationContext获取WebApplicationContext ,之后判断是否为空,为空时执行createWebApplicationContext方法 |
| protected WebApplicationContext initWebApplicationContext() { |
| WebApplicationContext rootContext = |
| WebApplicationContextUtils.getWebApplicationContext(getServletContext()); |
| WebApplicationContext wac = null; |
| |
| if (this.webApplicationContext != null) { |
| |
| wac = this.webApplicationContext; |
| if (wac instanceof ConfigurableWebApplicationContext) { |
| ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac; |
| if (!cwac.isActive()) { |
| |
| |
| if (cwac.getParent() == null) { |
| |
| |
| cwac.setParent(rootContext); |
| } |
| configureAndRefreshWebApplicationContext(cwac); |
| } |
| } |
| } |
| if (wac == null) { |
| |
| |
| |
| |
| wac = findWebApplicationContext(); |
| } |
| if (wac == null) { |
| |
| wac = createWebApplicationContext(rootContext); |
| } |
| |
| if (!this.refreshEventReceived) { |
| |
| |
| |
| synchronized (this.onRefreshMonitor) { |
| onRefresh(wac); |
| } |
| } |
| |
| if (this.publishContext) { |
| |
| String attrName = getServletContextAttributeName(); |
| getServletContext().setAttribute(attrName, wac); |
| } |
| |
| return wac; |
| } |
| |
| # 查看createWebApplicationContext方法,调用createWebApplicationContext方法 |
| protected WebApplicationContext createWebApplicationContext(@Nullable WebApplicationContext parent) { |
| return createWebApplicationContext((ApplicationContext) parent); |
| } |
| |
| # 查看createWebApplicationContext方法 |
| protected WebApplicationContext createWebApplicationContext(@Nullable ApplicationContext parent) { |
| Class<?> contextClass = getContextClass(); |
| 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; |
| } |
| |
| # 回到FrameworkServlet类的initWebApplicationContext方法中 |
| if (wac == null) { |
| |
| wac = createWebApplicationContext(rootContext); |
| } |
| if (!this.refreshEventReceived) { |
| |
| |
| |
| synchronized (this.onRefreshMonitor) { |
| |
| onRefresh(wac); |
| } |
| } |
| |
| if (this.publishContext) { |
| |
| String attrName = getServletContextAttributeName(); |
| |
| getServletContext().setAttribute(attrName, wac); |
| } |
| |
| # 查看onRefresh方法 |
| protected void onRefresh(ApplicationContext context) { |
| |
| } |
| |
| # 查看DispatcherServlet中的onRefresh方法,它重写的是FrameworkServlet类中的onRefresh方法 |
| @Override |
| protected void onRefresh(ApplicationContext context) { |
| initStrategies(context); |
| } |
| |
| # 查看initStrategies方法 |
| protected void initStrategies(ApplicationContext context) { |
| |
| initMultipartResolver(context); |
| initLocaleResolver(context); |
| initThemeResolver(context); |
| |
| initHandlerMappings(context); |
| |
| initHandlerAdapters(context); |
| |
| initHandlerExceptionResolvers(context); |
| initRequestToViewNameTranslator(context); |
| |
| initViewResolvers(context); |
| initFlashMapManager(context); |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?