多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國(guó)內(nèi)最全I(xiàn)T社區(qū)平臺(tái) 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁(yè) > php開源 > php教程 > Spring 源碼解析之DispatcherServlet源碼解析(五)

Spring 源碼解析之DispatcherServlet源碼解析(五)

來(lái)源:程序員人生   發(fā)布時(shí)間:2016-06-14 09:25:50 閱讀次數(shù):2921次

Spring 源碼解析之DispatcherServlet源碼解析(5)

前言

本文需要有前4篇文章的基礎(chǔ),才能夠清晰易懂,有興趣可以先看看詳細(xì)的流程,這篇文章可以說(shuō)是第1篇文章,也能夠說(shuō)是前4篇文章的的匯總,Spring的全部要求流程都是圍繞著DispatcherServlet進(jìn)行的

類結(jié)構(gòu)圖

Renderings

根據(jù)類的結(jié)構(gòu)來(lái)講DispatcherServlet本身也是繼承了HttpServlet的,所有的要求都是根據(jù)這1個(gè)Servlet來(lái)進(jìn)行轉(zhuǎn)發(fā)的,同時(shí)解釋了為何需要在web.xml進(jìn)行以下配置,由于Spring是基于1個(gè)Servlet來(lái)展開的,固然不需要Servlet也能夠使用Spring

<servlet> <servlet-name>appServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/spring-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>appServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>

1 DispatcherServlet初始化

1.1 DispatcherServlet初始化加載的幾個(gè)bean

protected void initStrategies(ApplicationContext context) { //初始化文件上傳處理類 initMultipartResolver(context); //初始化本地化Resolver initLocaleResolver(context); //初始化主題Resolver initThemeResolver(context); //初始化1些個(gè)與處理的HandlerMappings initHandlerMappings(context); // initHandlerAdapters(context); //初始化異常處理的handler initHandlerExceptionResolvers(context); //初始化要求路徑轉(zhuǎn)換為ViewName 的Translator initRequestToViewNameTranslator(context); //初始化ViewResolvers 這個(gè)就是針對(duì)視圖處理的Resolvers 比如jsp處理Resolvers 或freemarker處理Resolvers initViewResolvers(context); //初始化 主要管理flashmap,比如RedirectAttributes 的屬性會(huì)放到這個(gè)里面,默許使用的是SessionFlashMapManager initFlashMapManager(context); }

1.2 初始化流程圖

Renderings

1.2.1 HttpServletBean源碼解析

HttpServletBean本身來(lái)講是1個(gè)普通的servlet而已,主要做1些資源的初始化

public abstract class HttpServletBean extends HttpServlet implements EnvironmentCapable, EnvironmentAware { protected final Log logger = LogFactory.getLog(getClass()); /** * Set of required properties (Strings) that must be supplied as * config parameters to this servlet. */ private final Set<String> requiredProperties = new HashSet<String>(); private ConfigurableEnvironment environment; /** * Subclasses can invoke this method to specify that this property * (which must match a JavaBean property they expose) is mandatory, * and must be supplied as a config parameter. This should be called * from the constructor of a subclass. * <p>This method is only relevant in case of traditional initialization * driven by a ServletConfig instance. * @param property name of the required property */ protected final void addRequiredProperty(String property) { this.requiredProperties.add(property); } /** * 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. try { //使用Servlet配置的初始化參數(shù)創(chuàng)建1個(gè)PropertyValues對(duì)象,PropertyValues對(duì)象是名值對(duì)的集合, 子類也能夠指定哪些屬性是必須的 PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties); //把當(dāng)前的Servlet當(dāng)作1個(gè)Bean, 把Bean的屬性和屬性的存取方法信息放入BeanWrapper對(duì)象 BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this); //注冊(cè)1個(gè)可以在資源和路徑之間進(jìn)行轉(zhuǎn)化的客戶化編輯器,這些資源是這個(gè)Web利用的內(nèi)部資源,例如,1個(gè)文件,1個(gè)圖片等等 ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext()); bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment())); //提供給子類機(jī)會(huì)增加更多的客戶化的編輯器,或?qū)eanWrapper進(jìn)行更多的初始化 initBeanWrapper(bw); //把初始化制定的參數(shù)值賦值到Servlet的屬性中,第2個(gè)參數(shù)true表明疏忽位置屬性 bw.setPropertyValues(pvs, true); } catch (BeansException ex) { logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex); throw ex; } // Let subclasses do whatever initialization they like. //提供給子類的的初始化方法 目前是FrameworkServlet 進(jìn)行了實(shí)現(xiàn) initServletBean(); if (logger.isDebugEnabled()) { logger.debug("Servlet '" + getServletName() + "' configured successfully"); } } /** * Initialize the BeanWrapper for this HttpServletBean, * possibly with custom editors. * <p>This default implementation is empty. * @param bw the BeanWrapper to initialize * @throws BeansException if thrown by BeanWrapper methods * @see org.springframework.beans.BeanWrapper#registerCustomEditor */ protected void initBeanWrapper(BeanWrapper bw) throws BeansException { } /** * Overridden method that simply returns {@code null} when no * ServletConfig set yet. * @see #getServletConfig() */ @Override public final String getServletName() { return (getServletConfig() != null ? getServletConfig().getServletName() : null); } /** * Overridden method that simply returns {@code null} when no * ServletConfig set yet. * @see #getServletConfig() */ @Override public final ServletContext getServletContext() { return (getServletConfig() != null ? getServletConfig().getServletContext() : null); } /** * Subclasses may override this to perform custom initialization. * All bean properties of this servlet will have been set before this * method is invoked. * <p>This default implementation is empty. * @throws ServletException if subclass initialization fails */ protected void initServletBean() throws ServletException { } /** * {@inheritDoc} * @throws IllegalArgumentException if environment is not assignable to * {@code ConfigurableEnvironment}. */ @Override public void setEnvironment(Environment environment) { Assert.isInstanceOf(ConfigurableEnvironment.class, environment); this.environment = (ConfigurableEnvironment) environment; } /** * {@inheritDoc} * <p>If {@code null}, a new environment will be initialized via * {@link #createEnvironment()}. */ @Override public ConfigurableEnvironment getEnvironment() { if (this.environment == null) { this.environment = this.createEnvironment(); } return this.environment; } /** * Create and return a new {@link StandardServletEnvironment}. Subclasses may override * in order to configure the environment or specialize the environment type returned. */ protected ConfigurableEnvironment createEnvironment() { return new StandardServletEnvironment(); } /** * PropertyValues implementation created from ServletConfig init parameters. */ //主要是用來(lái)添加初始化參數(shù)的 private static class ServletConfigPropertyValues extends MutablePropertyValues { /** * Create new ServletConfigPropertyValues. * @param config ServletConfig we'll use to take PropertyValues from * @param requiredProperties set of property names we need, where * we can't accept default values requiredProperties 這個(gè)參數(shù)主要是指定初始化時(shí)必須添加的參數(shù) * @throws ServletException if any required properties are missing */ public ServletConfigPropertyValues(ServletConfig config, Set<String> requiredProperties) throws ServletException { Set<String> missingProps = (requiredProperties != null && !requiredProperties.isEmpty()) ? new HashSet<String>(requiredProperties) : null; Enumeration<String> en = config.getInitParameterNames(); while (en.hasMoreElements()) { String property = en.nextElement(); Object value = config.getInitParameter(property); addPropertyValue(new PropertyValue(property, value)); if (missingProps != null) { missingProps.remove(property); } } // Fail if we are still missing properties. if (missingProps != null && missingProps.size() > 0) { throw new ServletException( "Initialization from ServletConfig for servlet '" + config.getServletName() + "' failed; the following required properties were missing: " + StringUtils.collectionToDelimitedString(missingProps, ", ")); } } } }

1.2.1 FrameworkServlet源碼解析

這里只貼初始化的需要的部份代碼,根據(jù)上面的邏輯,子類實(shí)現(xiàn)了initServletBean()這個(gè)方法進(jìn)行初始化

public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware { protected void initFrameworkServlet() throws ServletException { } //實(shí)現(xiàn)HttpServletBean 的初始化接口 @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 { //初始化webApplicationContext this.webApplicationContext = initWebApplicationContext(); //這個(gè)是留給子類去實(shí)現(xiàn)的方法,暫時(shí)來(lái)講沒有具體的實(shí)現(xiàn),主要是留給開發(fā)人員自定義1些特性的時(shí)候 //這個(gè)時(shí)候WebApplicationContext已被初始化了,也就是1些個(gè)spring的配置文件已被初始化了 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"); } } protected WebApplicationContext initWebApplicationContext() { //獲得根的Context對(duì)象,比如說(shuō)我用了Spring boot或注解的方式進(jìn)行初始化,那末這里的Context就是Spring boot或其他的context對(duì)象 WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); WebApplicationContext wac = null; //如果當(dāng)前的webApplicationContext 不等于null if (this.webApplicationContext != null) { // A context instance was injected at construction time -> use it wac = this.webApplicationContext; //如果context對(duì)象是ConfigurableWebApplicationContext if (wac instanceof ConfigurableWebApplicationContext) { ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac; //如果ConfigurableWebApplicationContext 不是存活狀態(tài) if (!cwac.isActive()) { // The context has not yet been refreshed -> provide services such as // setting the parent context, setting the application context id, etc //如果沒有設(shè)置過(guò)parent 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); } } } 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 //查詢當(dāng)前的Context,下述有詳細(xì)講授 wac = findWebApplicationContext(); } //如果沒有找到那末就通過(guò)rootContext 去創(chuàng)建1個(gè)Context對(duì)象 if (wac == null) { // No context instance is defined for this servlet -> create a local one wac = createWebApplicationContext(rootContext); } //如果允許通過(guò)事件通知,那末就直接初始化。通過(guò)事件的通知可以反向的說(shuō)明onRefresh()這個(gè)方法是可以被重復(fù)調(diào)用的,具體分析看下面 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); } // Publish the context as a servlet context attribute. //如果允許publish Context的話那末就把spring context放入到spring的ServletContext中 if (this.publishContext) { 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; } //創(chuàng)建and refresh WebApplicationContext protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) { //判斷id 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 information if (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()); //添加針對(duì)ContextRefreshListener事件的監(jiān)聽 //ApplicationListener decorator that filters events from a specified event source, invoking its delegate listener for matching ApplicationEvent objects only. //看了1下英文,大概是用了decorator(裝潢)模式,具體源碼里面,也只是做了1個(gè)簡(jiǎn)單的裝潢模式,這個(gè)類接受所有的ApplicationEvent事件 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 #refresh ConfigurableEnvironment env = wac.getEnvironment(); if (env instanceof ConfigurableWebEnvironment) { ((ConfigurableWebEnvironment) env).initPropertySources(getServletContext(), getServletConfig()); } //Post-process the given WebApplicationContext before it is refreshed //大概就是說(shuō),在初始化handlermapping和1些本地化等調(diào)用refresh方法之前處理WebApplicationContext,這個(gè)類沒有具體實(shí)現(xiàn),開發(fā)者可以自己去處理 postProcessWebApplicationContext(wac); //spring dispatcherServlet初始化的時(shí)候可以指定初始化1些類 applyInitializers(wac); //這個(gè)是重點(diǎn)方法,這里采取了事件的模式進(jìn)行通知,去調(diào)用refresh方法初始化配置 wac.refresh(); } //初始化spring context的時(shí)候 初始化1些指定需要初始化的類 這些類需要實(shí)現(xiàn)ApplicationContextInitializer 這個(gè)接口才能進(jìn)行調(diào)用 protected void applyInitializers(ConfigurableApplicationContext wac) { //獲得到ServletContext中初始化的類數(shù)組參數(shù) // String globalClassNames = getServletContext().getInitParameter(ContextLoader.GLOBAL_INITIALIZER_CLASSES_PARAM); if (globalClassNames != null) { //不斷的去初始化這個(gè)類數(shù)組 以,;\t\n等作為分隔符 for (String className : StringUtils.tokenizeToStringArray(globalClassNames, INIT_PARAM_DELIMITERS)) { this.contextInitializers.add(loadInitializer(className, wac)); } } if (this.contextInitializerClasses != null) { for (String className : StringUtils.tokenizeToStringArray(this.contextInitializerClasses, INIT_PARAM_DELIMITERS)) { this.contextInitializers.add(loadInitializer(className, wac)); } } //排序,可以指定這些類的初始化順序,通過(guò)@Order注解來(lái)實(shí)現(xiàn)排序 AnnotationAwareOrderComparator.sort(this.contextInitializers); //初始化 for (ApplicationContextInitializer<ConfigurableApplicationContext> initializer : this.contextInitializers) { initializer.initialize(wac); } } //初始化類, private ApplicationContextInitializer<ConfigurableApplicationContext> loadInitializer( String className, ConfigurableApplicationContext wac) { try { //加載這個(gè)類 Class<?> initializerClass = ClassUtils.forName(className, wac.getClassLoader()); //判斷是不是實(shí)現(xiàn)了接口ApplicationContextInitializer Class<?> initializerContextClass = GenericTypeResolver.resolveTypeArgument(initializerClass, ApplicationContextInitializer.class); if (initializerContextClass != null && !initializerContextClass.isInstance(wac)) { throw new ApplicationContextException(String.format( "Could not apply context initializer [%s] since its generic parameter [%s] " + "is not assignable from the type of application context used by this " + "framework servlet: [%s]", initializerClass.getName(), initializerContextClass.getName(), wac.getClass().getName())); } //初始化對(duì)象 return BeanUtils.instantiateClass(initializerClass, ApplicationContextInitializer.class); } catch (ClassNotFoundException ex) { throw new ApplicationContextException(String.format("Could not load class [%s] specified " + "via 'contextInitializerClasses' init-param", className), ex); } } }

上述代碼獲得root Context的時(shí)候可以通過(guò)以下代碼了解到獲得方式,webapp的Context對(duì)象的保存,其實(shí)不過(guò)就是把spring的context放到了ServletContext的1個(gè)屬性中而已

WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
public abstract class WebApplicationContextUtils { public static WebApplicationContext getWebApplicationContext(ServletContext sc) { return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); } /** * Find a custom {@code WebApplicationContext} for this web app. * @param sc ServletContext to find the web application context for * @param attrName the name of the ServletContext attribute to look for * @return the desired WebApplicationContext for this web app, or {@code null} if none */ public static WebApplicationContext getWebApplicationContext(ServletContext sc, String attrName) { Assert.notNull(sc, "ServletContext must not be null"); //通過(guò)從ServletContext 去獲得spring的context對(duì)象 Object attr = sc.getAttribute(attrName); if (attr == null) { return null; } if (attr instanceof RuntimeException) { throw (RuntimeException) attr; } if (attr instanceof Error) { throw (Error) attr; } if (attr instanceof Exception) { throw new IllegalStateException((Exception) attr); } if (!(attr instanceof WebApplicationContext)) { throw new IllegalStateException("Context attribute is not of type WebApplicationContext: " + attr); } return (WebApplicationContext) attr; } }

wac = findWebApplicationContext(); 上述這塊邏輯主要是通過(guò)獲得ContextAttribute的屬性名去ServletContext中獲得Context對(duì)象

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; }

1.2.2 FrameworkServlet 中refresh源碼解析

這里流程比較繁瑣,重點(diǎn)講述1下 wac.refresh(); 這個(gè)方法會(huì)調(diào)用AbstractApplicationContext這里類面的refresh去實(shí)現(xiàn)相應(yīng)的邏輯,這個(gè)類具體的英文解釋(implements common context functionality. Uses the Template Method design pattern) 大概意思就是說(shuō)實(shí)現(xiàn)了1些公有的方法,通過(guò)Template Method這類設(shè)計(jì)模式實(shí)現(xiàn)功能,其實(shí)也就是將邏輯放到了AbstractApplicationContext中,然后子類去實(shí)現(xiàn)各種方法。邏輯已由AbstractApplicationContext定好,子類不關(guān)心邏輯

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext, DisposableBean { //準(zhǔn)備刷新之前調(diào)用 protected void prepareRefresh() { //記錄開始時(shí)間 this.startupDate = System.currentTimeMillis(); //改變狀態(tài) this.closed.set(false); this.active.set(true); if (logger.isInfoEnabled()) { logger.info("Refreshing " + this); } // Initialize any placeholder property sources in the context environment //這個(gè)主要留給子類去實(shí)現(xiàn) initPropertySources(); // Validate that all properties marked as required are resolvable // see ConfigurablePropertyResolver#setRequiredProperties //校驗(yàn)必須初始化的參數(shù) getEnvironment().validateRequiredProperties(); // Allow for the collection of early ApplicationEvents, // to be published once the multicaster is available... this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>(); } //初始化1些beanFactory參數(shù) protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { // Tell the internal bean factory to use the context's class loader etc. //設(shè)置classLoader beanFactory.setBeanClassLoader(getClassLoader()); //設(shè)置bean表達(dá)式解析器 spring 的el 表達(dá)式 beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); //使用資源編輯器來(lái)填充指定的PropertyEditorRegistry。 beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); // Configure the bean factory with context callbacks. //負(fù)責(zé)注入ResourceLoaderAware, ApplicationEventPublisherAware, MessageSourceAware, ApplicationContextAware ApplicationContext相干特性的Bean beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); beanFactory.ignoreDependencyInterface(EnvironmentAware.class); // BeanFactory interface not registered as resolvable type in a plain factory. // MessageSource registered (and found for autowiring) as a bean. //This is intended for factory/context references that are supposed to be autowirable but are not defined as beans in the factory: e.g. a dependency of type ApplicationContext resolved to the ApplicationContext instance that the bean is living in. //上述英文大概意思就是定義了1個(gè)特殊的bean,但是這個(gè)bean不通過(guò) beanFactory進(jìn)行管理生命周期,beanFactory本身就是1個(gè)bean,本身管理本身就有點(diǎn)奇怪,所以這個(gè)方法是注冊(cè)1些特殊的bean,并且可以進(jìn)行注入 beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this); // Detect a LoadTimeWeaver and prepare for weaving, if found. if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); // Set a temporary ClassLoader for type matching. beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } // Register default environment beans. if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); } if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties()); } if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment()); } } @Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. //preparecontext之前履行的操作 prepareRefresh(); //告知子類刷新bean工廠,spring boot能夠做到改變1個(gè)類進(jìn)行熱部署,我猜可能就調(diào)用了這個(gè)刷新方法去刷新bean工廠,所以改變了1些靜態(tài)變量spring boot是不會(huì)動(dòng)態(tài)刷新的 // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. //初始化1些bean工廠的參數(shù) prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. // 增加處理servletContext的類 postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); //初始化消息源 // Initialize message source for this context. initMessageSource(); //初始化消息事件 // Initialize event multicaster for this context. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // Check for listener beans and register them. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); //發(fā)送refresh事件 // Last step: publish corresponding event. finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); } } } }

AbstractApplicationContext這個(gè)類比較繁瑣,這里只大概描寫了1下大概的功能,后續(xù)文章會(huì)詳細(xì)進(jìn)行講授,這里主要是講授初始化流程

Spring 整體流程圖

Renderings.png?dir=0&filepath=spring%2FsourceCode%2Fimg%2Fdipatcher+%281%29.png&oid=d32d3920eb9fa1afe65c08f70e5e3c3966ddd8e2&sha=de3a2aaf492d9bcacf82f1462d06bd50f6091186)

生活不易,碼農(nóng)辛苦
如果您覺得本網(wǎng)站對(duì)您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: 亚洲第一网站在线观看 | 欧美人与性另类 | 在线中文字幕网站 | 伊人久久大香线蕉免费视频 | 欧美性一区二区三区 | 久久国产精品影院 | 99www综合久久爱com | 好好的日视频www | 91免费福利 | 五月婷婷视频 | 免费在线中文字幕 | 尤物免费在线视频 | 成人一级大片 | 亚洲码在线中文在线观看 | 中文字幕乱码一区三区免费 | 日本三级s级在线播放 | 久久福利影院 | 伊人精品成人久久综合欧美 | 日韩欧美中文字幕一区二区三区 | 亚洲精品久久久久久久久久ty | 国产国产人在线成免费视频69 | 国产精品免费视频一区二区 | 91久久另类重口变态 | 娇小性色xxxxx中文 | 亚洲日本视频在线 | 欧美最猛黑人xxxx黑人猛交98 | 国产成人精品一区二区 | 国产尤物在线视频 | 亚洲国产aaa毛片无费看 | 综合久久久| 亚洲video| 欧美视频亚洲 | 亚洲精品天堂在线 | 在线视频综合视频免费观看 | 岛国视频在线播放 | 日本视频一区二区三区 | 亚洲欧美日韩另类小说 | 黑人疯狂做人爱视频 | 日韩在线观看一区 | 欧美日本在线观看 | 欧美日韩国产成人综合在线 |