|
From: Rob B. <rob...@ve...> - 2004-01-12 17:54:06
|
Hello all, The various implementations of the ConfigurableApplicationContext refresh() method do not appear to be threadsafe. I check M4 code base, but it looks like it was never threadsafe in any of the previous implementations either (M2 wasn't threadsafe either). Let's use XmlWebApplicationContext as an example. First of all the refresh method in AbstractApplicationContext (a super class of XmlWebApplicationContext) should probably be syncronized so that two threads cannot call refresh at the same time (potential race condition in configuring two bean factories simultaneously). Secondly if refresh is called, any thread which calls getBeanFactory() before refresh is completed may not get a fully configured bean factory. AbstractApplicationContext.refresh() calls AbstractXmlApplicationContext.refreshBeanFactory(), from this point on until the refresh method is finished any calls to getBeanFactory are returning a bean factory that is in the process of being configured, but is not yet ready for use in the application. AbstractApplicationContext.refresh() then takes advantage of that fact to continue the processing needed to complete the configuration of the bean factory. A non-threadsafe implementation of ConfigurableApplicationContext may not be a problem in a GUI application where we have complete control over threads, but should not be used in an application / environment (Like a servlet / ejb container) where we don't. Everything is threadsafe as long as your app never needs to call refresh(), but then that requires you to restart your web app to change any configuration properties. One potential way to fix the threading issue may be to add a few methods to ConfigurableApplicationContext. 1) getLoadingBeanFactory() - Returns the bean factory that is in the process of being loaded. 2) beanFactoryLoaded() - Informs sub-classes that the bean factory configuration is complete and they should now return the new bean factory in any requests to getBeanFactory() Modify all code that calls getBeanFactory() during loading to call getLoadingBeanFactory() instead. Modify AbstractXmlApplicationContext to have both a loading & live bean factory class variables. When beanFactoryLoaded() is called then live = loading, loading = null. An alternative is to modify refreshBeanFactory() to return the bean factory object it created instead of setting this.beanfactory. Then refresh() in AbstractApplicationContext should be modified to use the returned bean factory, along with all the methods it calls. The method beanFactoryLoaded() method could be implemented to accept a parameter instead of no parameter as indicated above. Thus it would be beanFactoryLoaded(ConfigurableListableBeanFactory newBeanFactory). AbstractXmlApplicationContext would then know to use the new bean factory that was passed from that point on, and getLoadingBeanFactory() would not be needed. Later Rob |