Let's introduce:
Beannameurlhandlermapping is a configuration file-based approach; All processors need to be configured in the XML file in the form of beans.
Disadvantages: Cumbersome configuration; If more than one URL corresponds to the same processor, you need to configure more than one, and also instantiate multiple objects and so on ...
Because SPRINGMVC is based on spring, his initialization must have been done after the spring container was initialized.
First, the class diagram:
You can see that the Beannameurlhandlermapping parent class eventually implements the Applicationcontextaware interface, so the spring container will automatically inject ApplicationContext by:
1 PublicFinalvoidSetapplicationcontext (ApplicationContext context) throws Beansexception {2 if(Context = =NULL&&! This. iscontextrequired ()) {3 This. ApplicationContext =NULL;4 This. Messagesourceaccessor =NULL;5}Else if( This. ApplicationContext = =NULL) {6 if(! This. Requiredcontextclass (). Isinstance (context)) {7 Throw NewApplicationcontextexception ("Invalid application Context:needs to be of type ["+ This. Requiredcontextclass (). GetName () +"]");8 }9 Ten This. ApplicationContext =context; One This. Messagesourceaccessor =Newmessagesourceaccessor (context); A This. Initapplicationcontext (context); This block is actually a hook method for subclasses to overwrite! Perform initialization work -}Else if( This. applicationcontext! =context) { - Throw NewApplicationcontextexception ("cannot reinitialize with different application context:current one is ["+ This. ApplicationContext +"], passed-in one is ["+ Context +"]"); the } - -}
Abstracthandlermapping: This class is a replication of this method for the initialization of interceptors
protected void Initapplicationcontext () throws Beansexception { this. Extendinterceptors. Interceptors); For sub-class extension interceptors this. Detectmappedinterceptors (this . mappedinterceptors);// Scan the Mappedinterceptor under application and add to Mappedinterceptorsthis. initinterceptors ();// Collect mappedinterceptor and adapt to Handlerinterceptor and Webrequestinterceptor }
Abstractdetectingurlhandlermapping: Also rewrite this method to implement your own logic
1 Public voidInitapplicationcontext () throws Applicationcontextexception {2 Super.initapplicationcontext ();3 This. Detecthandlers ();4 }5 6 protected voidDetecthandlers () throws Beansexception {7 if( This. logger.isdebugenabled ()) {8 This. Logger.debug ("looking for URL mappings in application context:"+ This. Getapplicationcontext ());9 }TenScan all the object classes under Application Onestring[] Beannames = This. detecthandlersinancestorcontexts? Beanfactoryutils.beannamesfortypeincludingancestors ( This. Getapplicationcontext (), Object.class) : This. Getapplicationcontext (). Getbeannamesfortype (Object.class); Astring[] arr$ =Beannames; - intlen$ =beannames.length; - the for(inti$ =0; i$ < len$; ++i$) {//traversal of each scanned class -String Beanname =arr$[i$]; -string[] URLs = This. Determineurlsforhandler (Beanname);//Hook method, let subclasses to implement, through handler parse URL - if(!objectutils.isempty (URLs)) { + This. Registerhandler (URLs, beanname);//The returned URL is registered, which is actually placed in a map of abstracturlhandlermapping -}Else if( This. logger.isdebugenabled ()) { + This. Logger.debug ("rejected Bean name '"+ Beanname +"': No URL paths identified"); A } at } - -}
Beannameurlhandlermapping: In fact, this method of Determineurlsforhandler is implemented:
////Source code recreated from a. class file by IntelliJ idea//(Powered by Fernflower Decompiler)//Package Org.springframework.web.servlet.handler;import Java.util.arraylist;import java.util.list;import Org.springframework.util.StringUtils; Public classBeannameurlhandlermapping extends Abstractdetectingurlhandlermapping { Publicbeannameurlhandlermapping () {}protectedstring[] Determineurlsforhandler (String beanname) {List<String> URLs =NewArrayList (); if(Beanname.startswith ("/") {//Only one thing to note is that the Bean ID must start with '/' Urls.add (beanname); } string[] Aliases= This. Getapplicationcontext (). getaliases (Beanname); String[] arr$=aliases; intlen$ =aliases.length; for(inti$ =0; i$ < len$; ++i$) {String alias=arr$[i$]; if(Alias.startswith ("/") {urls.add (alias); } } returnStringutils.tostringarray (URLs); }}
Abstracturlhandlermappin: How to register the processor in:
1 protected voidRegisterhandler (String URLPath, Object handler) throws Beansexception, IllegalStateException {2Assert.notnull (URLPath,"URL Path must not being null");3Assert.notnull (Handler,"Handler object must not being null");4Object Resolvedhandler =handler;5 if(! This. lazyinithandlers &&handler instanceof String) {6String HandlerName =(String) handler;7 if( This. Getapplicationcontext (). Issingleton (HandlerName)) {8Resolvedhandler = This. Getapplicationcontext (). Getbean (handlerName);9 }Ten } One AObject Mappedhandler = This. Handlermap.Get(URLPath); - if(Mappedhandler! =NULL) { - if(Mappedhandler! =Resolvedhandler) {//Do not allow the same URL to be different handler, otherwise throw exception the Throw NewIllegalStateException ("cannot map"+ This. Gethandlerdescription (Handler) +"to URL path ["+ URLPath +"]: There is already"+ This. Gethandlerdescription (Mappedhandler) +"mapped."); - } -}Else if(Urlpath.equals ("/")) { - if( This. logger.isinfoenabled ()) { + This. Logger.info ("Root Mapping to"+ This. Gethandlerdescription (handler)); - } + A This. Setroothandler (Resolvedhandler); at}Else if(Urlpath.equals ("/*")) { - if( This. logger.isinfoenabled ()) { - This. Logger.info ("Default Mapping to"+ This. Gethandlerdescription (handler)); - } - - This. Setdefaulthandler (Resolvedhandler); in}Else{//This is the normal storage logic - This. Handlermap.put (URLPath, resolvedhandler); to if( This. logger.isinfoenabled ()) { + This. Logger.info ("Mapped URL Path ["+ URLPath +"] onto"+ This. Gethandlerdescription (handler)); - } the } * $}
In fact, the storage of the processor mapper is done.
In fact handlermapping this piece, the main idea is to write a template class, to deal with public methods, such as the initialization of interceptors, and then leave the hook method, so that the subclass to implement their own logic just fine.
Spring MVC's handlermapping beannameurlhandlermapping initialization