It is currently possible to autowire against an ApplicationContext that has been closed. However, attempting to do so should result in some sort of exception being thrown. See the example failing tests below.
This issue was brought to our attention when integration tests in the Spring Integration test suite started failing. See INT-3543 for details.
Analysis by Jürgen Höller
AbstractApplicationContext already invokes assertBeanFactoryActive() before it delegates to the internal DefaultListableBeanFactory but of course only for methods on the ApplicationContext itself.
The underlying BeanFactory doesn't have the notion of a 'closed' state -- it may just have had its singletons destroyed but could, from its perspective, recreate them at any point.
The semantically cleaner solution is to perform the assertion in the application context's getAutowireCapableBeanFactory() implementation: AbstractRefreshableApplicationContext subclasses do throw an IllegalStateException there after closing, but GenericApplicationContext subclasses don't. The latter needs to be fixed, and the getAutowireCapableBeanFactory() Javadoc in the ApplicationContext interface needs to explicitly state that an IllegalStateException will be thrown after context closing.
Example Failing Tests
Example1Test does not fail until the second line of the test2() method, thus demonstrating that the test instance was autowired from a closed ApplicationContext.
Example2Test contains a copy of the actual code from DependencyInjectionTestExecutionListener.injectDependencies(), demonstrating that autowiring against a closed ApplicationContext in fact does not throw any kind of exception.
ApplicationContext.getAutowireCapableBeanFactory() always declared that it may throw IllegalStateException before initialization and after closing. I added a forward-looking notice back in 4.1.2, preparing for consistent throwing from a GenericApplicationContext in 4.2. For some reason I never got around to creating an issue for it, so here we go with this one now :-)
For anyone depending on the previous behavior, i.e. doing getAutowireCapableBeanFactory() calls after closing, such code would have been GenericApplicationContext dependent anyway. Switching such code to ConfigurableApplicationContext.getBeanFactory() should do the job, still returning the underlying BeanFactory without any lifecycle checks.