Spring's refresh () method related exceptions

Source: Internet
Author: User
Tags throw exception

If you are a frequent user of spring, especially those who have created a new ApplicationContext object, you must have seen a few exceptions:
1.LifecycleProcessor not Initialized-call ' refresh ' before invoking lifecycle methods via the context: ...
2.BeanFactory not initialized or already closed-call ' refresh ' before accessing beans via the ApplicationContext
3.ApplicationEventMulticaster not Initialized-call ' refresh ' before multicasting events via the context: ...

The first message is that the Lifecycleprocessor object is not initialized, and the ' refresh ' method must be called before the life-cycle method of the context is called
The second message is that the Beanfactory object is not initialized or closed, and the ' refresh ' method must be called before using ApplicationContext to get the bean
The third message is that the Applicationeventmulticaster object is not initialized, and the ' refresh ' method must be called before the context broadcast event

These exception messages are all related to the Refresh method, the reason why these exceptions are thrown, and why in so many cases it is important to call the Refresh method first (defined in the Abstractapplicationcontext Class), Let's look at what we did in the Refresh method first.

 

public void Refresh () throws Beansexception, IllegalStateException {synchronized (this.startupshutdownmonitor) {// Pre-refresh preparation, including setting the startup time, whether to activate the identity bit, initialize the property source Configuration Preparerefresh (), or subclass to refresh Beanfactory (created if not already created), and return beanfactory to configurablelistablebeanfactory beanfactory = Obtainfreshbeanfactory ();// Prepare beanfactory for ApplicationContext use Preparebeanfactory (beanfactory); try {// Subclasses can format this method to modify the Beanfactory postprocessbeanfactory (beanfactory);// Instantiate and invoke all registered Beanfactorypostprocessor objects invokebeanfactorypostprocessors (beanfactory);// Instantiate and invoke all registered Beanpostprocessor objects registerbeanpostprocessors (beanfactory);//Initialize Messagesourceinitmessagesource ();// Initialize event broadcaster Initapplicationeventmulticaster ();//Subclasses override this method to do extra work during the refresh process Onrefresh ();// Register the Application Listener applicationlistenerregisterlisteners ();//Instantiate All Non-lazy-init beanfinishbeanfactoryinitialization ( beanfactory);//refresh complete work, including initialization lifecycleprocessor, publish refresh completion events, etc. finishrefresh ();} catch (Beansexception ex) {//Destroy already created singletons to avoid dangling resources.destroybeans ();//ReseT ' active ' Flag.cancelrefresh (ex);//Propagate exception to Caller.throw Ex;}}} 


The methods associated with this three exception messages are: Finishrefresh (); Obtainfreshbeanfactory (); Initapplicationeventmulticaster ();

protected void Finishrefresh () {/////Initialize Lifecycleprocessorinitlifecycleprocessor ();//Propagate Refresh to Lifecycle Processor First.getlifecycleprocessor (). Onrefresh ();//Publish The final event.publishevent (new Contextrefreshedevent (this));//participate in Livebeansview MBean, if active. Livebeansview.registerapplicationcontext (this);}


If the Finishrefresh method is not called, the Lifecycleprocessor member is null.

Protected Configurablelistablebeanfactory obtainfreshbeanfactory () {refreshbeanfactory ();//Refresh Beanfactory, If beanfactory is null, configurablelistablebeanfactory beanfactory = Getbeanfactory () is created, if (logger.isdebugenabled ()) { Logger.debug ("Bean factory for" + getdisplayname () + ":" + beanfactory);} return beanfactory;}


Refreshbeanfactory () is an abstract method that is actually implemented in the Abstractrefreshableapplicationcontext class:

@Overrideprotected final void Refreshbeanfactory () throws Beansexception {if (Hasbeanfactory ()) {// If the beanfactory is not already null, then the bean in Beanfactory is destroyed and closed by itself Destroybeans (); Closebeanfactory (); try {defaultlistablebeanfactory beanfactory = createbeanfactory ();//Create Beanfactorybeanfactory.setserializationid ( GetId ()); Customizebeanfactory (beanfactory); loadbeandefinitions (beanfactory); synchronized ( This.beanfactorymonitor) {this.beanfactory = beanfactory;//assignment to beanfactory member}}catch (IOException ex) {throw new Applicationcontextexception ("I/O error parsing bean definition source for" + GetDisplayName (), ex);}}


If the Obtainfreshbeanfactory () method is not called, the Beanfactory member is null.

protected void Initapplicationeventmulticaster () {configurablelistablebeanfactory Beanfactory = Getbeanfactory (); if (Beanfactory.containslocalbean (Application_event_multicaster_bean_name)) { This.applicationeventmulticaster =beanfactory.getbean (Application_event_multicaster_bean_name, Applicationeventmulticaster.class), if (logger.isdebugenabled ()) {Logger.debug ("Using applicationeventmulticaster [ "+ This.applicationeventmulticaster +"] ");}} else {this.applicationeventmulticaster = new Simpleapplicationeventmulticaster (beanfactory); Beanfactory.registersingleton (Application_event_multicaster_bean_name, This.applicationeventmulticaster); Logger.isdebugenabled ()) {Logger.debug ("Unable to locate Applicationeventmulticaster with name '" +application_event_ Multicaster_bean_name + "': Using default [" + This.applicationeventmulticaster + "]");}}} 


And these three method calls are all in the Refresh () method, the above analysis shows that if the Refresh method is not called, then the context of the lifecycleprocessor,beanfactory, The Applicationeventmulticaster member will be null. You can now analyze the reasons for these three exception messages in detail.
The following is the three-segment test code for the three exception messages above, which corresponds to the order:

1. public static void Main (string[] args) {Classpathxmlapplicationcontext ApplicationContext = new Classpathxmlapplicationcontext (); Applicationcontext.setconfiglocation ("Application-context.xml"); Applicationcontext.start (); Applicationcontext.close ();} 2. public static void Main (string[] args) {Classpathxmlapplicationcontext ApplicationContext = new Classpathxmlapplicationcontext (); Applicationcontext.setconfiglocation ("Application-context.xml"); Applicationcontext.getbean ("XTAYFJPK"); Applicationcontext.close ();} 3. public static void Main (string[] args) {Genericapplicationcontext parent = new Genericapplicationcontext (); Annotationconfigwebapplicationcontext context = new Annotationconfigwebapplicationcontext (); Context.setparent ( parent); Context.refresh (); Context.start (); Context.close ();}


For the first exception message, the exception stack error is in Applicationcontext.start (); The following is the start () method source code:

public void Start () {Getlifecycleprocessor (). Start ();p ublishevent (new contextstartedevent);}


You can see that the start () method gets the Lifecycleprocessor object first, and the default constructor method does not call the Refresh method, so lifecycleprocessor is null, Therefore, this exception message is thrown in the Getlifecycleprocessor () method. This refers to the life cycle approach, in fact, is defined in the Org.springframework.context.Lifecycle Interface start (), Stop (), IsRunning () three methods, if it is just beginning to learn spring, This should be the case when creating the Classpathxmlapplicationcontext object: Classpathxmlapplicationcontext applicationcontext = new Classpathxmlapplicationcontext ("Application-context.xml"), so the direct call to the start () method without an exception is why? This is because Classpathxmlapplicationcontext (String configlocation) is ultimately called by the constructor method:

Public Classpathxmlapplicationcontext (string[] configlocations, Boolean refresh, ApplicationContext parent) throws Beansexception {super (parent); Setconfiglocations (configlocations); if (refresh) {//refresh Pass value is true, This automatically calls the Refresh method and refreshes it ();}}

Second exception message, exception stack error in Applicationcontext.getbean ("XTAYFJPK"), Applicationcontext.getbean () The method is called by the Beanfactory Getbean () method in the context to obtain the Beanfactory object's code in its base class Configurablelistablebeanfactory getbeanfactory () Method:

@Overridepublic final Configurablelistablebeanfactory getbeanfactory () {synchronized (this.beanfactorymonitor) {if ( This.beanfactory = = null) {throw new IllegalStateException ("Beanfactory not initialized or already closed –" + "call" Refr Esh ' before accessing beans via the ApplicationContext ');} return this.beanfactory;}}


Because the default constructor method for Classpathxmlapplicationcontext does not call the Refresh () method, Beanfactory is null and throws an exception.

The third exception message, the exception stack error is Context.refresh (), but if the parent context is not set context.setparent (parent), the example code does not appear to be abnormal. This is because the Finishrefresh () method in the Refresh method calls the Publishevent method:

public void Publishevent (Applicationevent event) {Assert.notnull (event, ' event must not ' be null '); Logger.istraceenabled ()) {Logger.trace ("publishing event in" + GetDisplayName () + ":" + Event); Getapplicationeventmulticaster (). Multicastevent (event); if (this.parent! = null) {this.parent.publishEvent (event);}}


As you can see from above: If the parent context is not NULL, you also need to call the parent container's Pushlishevent method, and in that method call the Getapplicationeventmulticaster () method to get an event broadcaster. This is where the problem arises:

Private Applicationeventmulticaster Getapplicationeventmulticaster () throws IllegalStateException {if ( This.applicationeventmulticaster = = null) {//If NULL then throw exception throw new IllegalStateException (" Applicationeventmulticaster not initialized-"+" call ' Refresh ' before multicasting events via the context: "+ this);} return this.applicationeventmulticaster;}


And Applicationeventmulticaster is the Initapplicationeventmulticaster method in the Refresh method is instantiated, The Refresh method is not called in the parent context so the Applicationeventmulticaster member of the parent context is null and therefore throws an exception.

In summary, in fact, the root cause of the three exception messages is only one, that is, when a context object is created, the Refresh () method is not called. There are many ApplicationContext implementation classes in spring, some implementation classes automatically call the Refresh () method during creation, and some do not, and if not, you need to call the Refresh () method manually. In general, implementation classes that implement the Webapplicationcontext interface and do not automatically refresh () methods when creating context objects using the default construction method, and others are automatically called.

Spring's refresh () method related exceptions

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.