Dispatcherservlet
Through the source code we can see that the Onrefresh method is the dispatcherservlet of the entrance method. In Onrefresh, the initstrategies was simply called, and 9 initialization methods were called in Initstrategies.
// Org.springframework.web.servlet.DispatcherServlet protected void Onrefresh (ApplicationContext context) { initstrategies (context);} protected void initstrategies (ApplicationContext context) { initmultipartresolver (context); Initlocaleresolver (context); Initthemeresolver (context); Inithandlermappings (context); Inithandleradapters (context); Inithandlerexceptionresolvers (context); Initrequesttoviewnametranslator (context); Initviewresolvers (context); Initflashmapmanager (context);}
We would like to: why not write the specific implementation of initstrategies directly into the Onrefresh? Isn't the Initstrategies method redundant?
In fact, this is mainly the reason for layering, Onrefresh is used to refresh the container, Initstrategies is used to initialize a number of policy components. If the code inside the initstrategies is written directly into the Onrefresh, there is no effect on the operation of the program, but in this way, if you want to add another function in Onrefresh, you will not write a method out of the logic clearly, but this is not the most important , and more importantly, if you need to call the Initstrategies method elsewhere (if you need to modify some policies for hot deployment), but Initstrategies is not independent, you can only call Onrefresh. That's a hassle when Onrefresh adds new features. In addition, the initstrategies can also be written out to cover the quilt class, using the new mode for initialization.
Initstrategies's specific content is very simple, is the initialization of the 9 components, the following localeresolver as an example to analyze the specific initialization://Initialize the Zone parser
//Org.springframework.web.servlet.DispatcherServletPrivate voidInitlocaleresolver (ApplicationContext context) {Try { //Get in context This. Localeresolver = Context.getbean (Locale_resolver_bean_name, Localeresolver.class); if(logger.isdebugenabled ()) {Logger.debug ("Using Localeresolver [" + This. Localeresolver + "]"); } }Catch(Nosuchbeandefinitionexception ex) {//using the default policy This. Localeresolver = Getdefaultstrategy (context, localeresolver.class); if(logger.isdebugenabled ()) {Logger.debug ("Unable to locate localeresolver with Name '" + Locale_resolver_bean_name + "': Using default [" + This. Localeresolver + "]"); } }}
The initialization method is divided into two steps: first by Context.getbean in the container by the name or type of registration (this refers to "localeresolver" name or Localeresolver.class type) to find, so in spring The MVC configuration file only needs to be configured with the appropriate type of component, and the container can be found automatically. If it is not found, call Getdefaultstrategy to get the default component by type. It is important to note that the context here refers to the Webapplicationcontext created in Frame-workservlet, not the ServletContext. Here's how getdefault-strategy gets the default components.
//Org.springframework.web.servlet.DispatcherServletprotected<T> T Getdefaultstrategy (applicationcontext context, class<t>strategyinterface) {List<T> strategies =getdefaultstrategies (context, strategyinterface); if(Strategies.size ()! = 1) { Throw NewBeaninitializationexception ("Dispatcherservlet needs exactly 1 strategy for interface [" + strategyinterface.getname () + "]"); } returnStrategies.get (0);}protected<T> list<t> getdefaultstrategies (applicationcontext context, class<t>strategyinterface) {String key=Strategyinterface.getname (); //get the type of policy you want from defaultstrategiesString value =Defaultstrategies.getproperty (key); if(Value! =NULL) { //If there are multiple default values, the comma is divided into arraysstring[] Classnames =Stringutils.commadelimitedlisttostringarray (value); List<T> strategies =NewArraylist<t>(classnames.length); //Initialize the policy by the type acquired for(String classname:classnames) {Try{Class<?> clazz = Classutils.forname (ClassName, Dispatcherservlet.class. getClassLoader ()); Object Strategy=createdefaultstrategy (context, clazz); Strategies.add ((T) strategy); }Catch(ClassNotFoundException ex) {Throw NewBeaninitializationexception ("Could not find Dispatcherservlet ' s default Strategy class [" + ClassName + "] for interface [" + K EY + "]", ex); }Catch(Linkageerror err) {Throw NewBeaninitializationexception ("Error loading Dispatcherservlet ' s default Strategy class [" + ClassName + "] for interface [" + Ke Y + "]: Problem with class file or dependent class", err); } } returnstrategies; }Else { return NewLinkedlist<t>(); }}
You can see that getdefaultstrategies is called in Getdefaultstrategy, which returns a list because components such as handlermapping can have more than one, So the Getdefaultstrategies method is defined, Getdefaultstrategy calls the Getdefaultstrategies method directly, and returns the first result of the return value. Getdefaultstrategies in the actual execution of the method is classutils.forname, it needs parameters is class-name, so the most important thing is to see ClassName How to come, found the source of classname, you can understand the default initialization mode. ClassName comes from Classnames,classnames and is from value, and value is from Default-strategies.getproperty (key). So the key point is in Defaultstrategies, Defaultstrategies is a static property that is initialized in a static block.
//Org.springframework.web.servlet.DispatcherServletPrivate Static FinalProperties defaultstrategies;Static { Try{Classpathresource Resource=NewClasspathresource (Default_strategies_path, Dispatcherservlet.class); Defaultstrategies=propertiesloaderutils.loadproperties (Resource); }Catch(IOException ex) {Throw NewIllegalStateException ("Could not load ' dispatcherservlet.properties ':" +ex.getmessage ()); }}
# org.springframework.web.dispatcherservlet.properties# Default Implementation Classes forDispatcherservlet ' s strategy interfaces.# used as fallback when no matching beans is found in the Dispatcherservlet context.# not meant to being customized by a Pplication developers.//these configurations are fixed and cannot be customized by developersOrg.springframework.web.servlet.LocaleResolver=Org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolverorg.springframework.web.servlet.ThemeResolver =org.springframework.web.servlet.theme.FixedThemeResolverorg.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping, Org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMappingorg.springframework.web.servlet.HandlerAdap ter=Org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter, Org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter, Org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapterorg.springframework.web.servlet.HandlerExcep Tionresolver=Org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver, Org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver, Org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolverorg.springframework.web.servlet.RequestToViewN Ametranslator=Org.springframework.web.servlet.view.DefaultRequestToViewNameTranslatororg.springframework.web.servlet.ViewResolver =Org.springframework.web.servlet.view.InternalResourceViewResolverorg.springframework.web.servlet.FlashMapManager =org.springframework.web.servlet.support.sessionflashmapmanager
We see that defaultstrategies is the attribute defined in the Default_strategies_path file under the package of the Dispatcherservlet class, Default_strategies_ The value of path is dispatcherservlet.properties. So the defaultstrategies inside is stored in the org.springframework.web.DispatcherServlet.properties inside the definition of the key value pair, code as above.
As you can see, the types of different components are defined here, there are 8 components defined, there is no default configuration to handle the upload component Multi-partresolver, it is easy to understand, not every application needs to upload function, Even if you need to upload, you don't have to use multipartresolver, so multipartresolver doesn't need a default configuration. In addition Handlermapping, Handleradapter and Handlerexceptionresolver are configured more than one, in fact, View-resolver can have more than just the default configuration only one.
Here are two questions to note: First, the default configuration is not the optimal configuration, nor is it the recommended configuration of spring, but there can be a default value when no configuration is available. Some of the default configurations are even labeled @deprecated, which means they are deprecated, such as defaultannotationhandlermapping, annotation-methodhandlersolver do not require a default configuration. In addition Handlermapping, Andleradapter and Handlerexceptionresolver are configured more than one, in fact, View-resolver can have more than just the default configuration only one.
The creation process of Dispatcherservlet is mainly to initialize the 9 large components, which are explained in detail after each component.
Java Framework-spring MVC Understanding 005-dispatcherservlet