Using spring boot has been almost 1 years, the period has always wanted to open springboot source view, but for various reasons have been unable to do so (mainly human inertia ...) ), today take the springboot of the monitoring event sacrificial knife.
Springboot commonly used in the event monitoring is mainly applicationstartedevent,applicationenviromentpreparedevent,applicationpreparedevent, Applicationstoppedevent and so on. Used to monitor various events in the Springboot life cycle.
When it comes to listening, the observer pattern, the Springboot event monitoring implementation is not an accident, its implementation mechanism is a typical observer pattern, but a little more complicated. Springboot The Observer into a list to delegate
Simpleapplicationeventmulticaster Management. Here's an interesting place where Srpingboot does not pass a normal path (such as new or other instantiation methods) when instantiating Springapplicationrunlistener, but instead passes the implementation class of the interface to
Springfactoriesloader to meta-inf/spring.factories under load:
Public StaticList<string> Loadfactorynames (class<?>Factoryclass, ClassLoader ClassLoader) {String Factoryclassname=Factoryclass.getname (); Try{Enumeration<URL> urls = (ClassLoader! =NULL?classloader.getresources (factories_resource_location): Classloader.getsystemresources (FACTORIES_R esource_location)); List<String> result =NewArraylist<string>(); while(Urls.hasmoreelements ()) {URL URL=urls.nextelement (); Properties Properties= Propertiesloaderutils.loadproperties (Newurlresource (URL)); String Factoryclassnames=Properties.getproperty (factoryclassname); Result.addall (Arrays.aslist (Stringutils.commadelimitedlisttostringarray (Factoryclassnames))); } returnresult; } Catch(IOException ex) {Throw NewIllegalArgumentException ("Unable to load [" + factoryclass.getname () + "] factories from location [" + Factories_resource_location + "]", ex); } }
Here, all meta-inf/spring.factories resources are loaded through the ClassLoader Getresources method.
Springboot why not at all cost to load an interface implementation, a little analysis is still very clear, first of all, the interface and implementation of separation, which is a typical dependency injection, if viewed from a single application, the big need not. The key is in the Springfactoriesloader, as stated above, Springfactoriesloader is to load all the configuration, that is, springboot in the future extension of the post, when there is a new jar package (which means that the upgrade again) Added, and you need to add a new listener event type, you don't have to modify the original code. This is the legendary example of a change-off opening to an extension.
Then, what exactly is the instance of Springfactoriesloader loading, eventpublishingrunlistener!
This goods is a middle class, to undertake the event of management and event broadcast, the real protagonist is the Simpleapplicationeventmulticaster class, the class of instances in the Eventpublishingrunlistener is created.
There's a listenerretriever inner class, this class has two functions, a default,simpleapplicationeventmulticaster is created when initialized, contains all the observers, and acts as a synchronous lock for various operations, There are two categories of observers, the basis for classification,
One is the event type EventType, and the other is the event primitive object type Sourcetype,sourcetype every event will have, here is applicationcontext. , when sorted, the notification is initiated by the topmost springapplication when the event occurs, and each specific observer is then called by the Simpleapplicationeventmulticaster object, respectively:
protected voidInvokelistener (Applicationlistener Listener, applicationevent event) {ErrorHandler ErrorHandler=Geterrorhandler (); if(ErrorHandler! =NULL) { Try{listener.onapplicationevent (event); } Catch(Throwable err) {errorhandler.handleerror (err); } } Else { Try{listener.onapplicationevent (event); } Catch(ClassCastException ex) {String msg=Ex.getmessage (); if(msg = =NULL||Msg.startswith (Event.getclass (). GetName ())) { //possibly a lambda-defined listener which we could not resolve the generic event type forLog logger =Logfactory.getlog (GetClass ()); if(logger.isdebugenabled ()) {Logger.debug ("Non-matching Event type for listener:" +Listener, ex); } } Else { Throwex; } } } }
At this point, a complete process from event registration to event departure to completion of event execution is completed. Mountain Road 18 bends, along the way the scenery is many, the fine taste still will have a harvest. There are still many details that could not be one by one, such as HashMap's hashcode rewrite analysis, such as the reason for the use of synchronization locks and so on.
Reprint please indicate the source.
Spring boot source appreciation of event monitoring