001/*
002 * Copyright 2002-2019 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.context.support;
018
019import java.io.IOException;
020import java.lang.annotation.Annotation;
021import java.util.ArrayList;
022import java.util.Collection;
023import java.util.Date;
024import java.util.LinkedHashSet;
025import java.util.List;
026import java.util.Locale;
027import java.util.Map;
028import java.util.Set;
029import java.util.concurrent.atomic.AtomicBoolean;
030
031import org.apache.commons.logging.Log;
032import org.apache.commons.logging.LogFactory;
033
034import org.springframework.beans.BeansException;
035import org.springframework.beans.CachedIntrospectionResults;
036import org.springframework.beans.factory.BeanFactory;
037import org.springframework.beans.factory.DisposableBean;
038import org.springframework.beans.factory.NoSuchBeanDefinitionException;
039import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
040import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
041import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
042import org.springframework.beans.support.ResourceEditorRegistrar;
043import org.springframework.context.ApplicationContext;
044import org.springframework.context.ApplicationContextAware;
045import org.springframework.context.ApplicationEvent;
046import org.springframework.context.ApplicationEventPublisher;
047import org.springframework.context.ApplicationEventPublisherAware;
048import org.springframework.context.ApplicationListener;
049import org.springframework.context.ConfigurableApplicationContext;
050import org.springframework.context.EmbeddedValueResolverAware;
051import org.springframework.context.EnvironmentAware;
052import org.springframework.context.HierarchicalMessageSource;
053import org.springframework.context.LifecycleProcessor;
054import org.springframework.context.MessageSource;
055import org.springframework.context.MessageSourceAware;
056import org.springframework.context.MessageSourceResolvable;
057import org.springframework.context.NoSuchMessageException;
058import org.springframework.context.PayloadApplicationEvent;
059import org.springframework.context.ResourceLoaderAware;
060import org.springframework.context.event.ApplicationEventMulticaster;
061import org.springframework.context.event.ContextClosedEvent;
062import org.springframework.context.event.ContextRefreshedEvent;
063import org.springframework.context.event.ContextStartedEvent;
064import org.springframework.context.event.ContextStoppedEvent;
065import org.springframework.context.event.SimpleApplicationEventMulticaster;
066import org.springframework.context.expression.StandardBeanExpressionResolver;
067import org.springframework.context.weaving.LoadTimeWeaverAware;
068import org.springframework.context.weaving.LoadTimeWeaverAwareProcessor;
069import org.springframework.core.ResolvableType;
070import org.springframework.core.convert.ConversionService;
071import org.springframework.core.env.ConfigurableEnvironment;
072import org.springframework.core.env.Environment;
073import org.springframework.core.env.StandardEnvironment;
074import org.springframework.core.io.DefaultResourceLoader;
075import org.springframework.core.io.Resource;
076import org.springframework.core.io.ResourceLoader;
077import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
078import org.springframework.core.io.support.ResourcePatternResolver;
079import org.springframework.util.Assert;
080import org.springframework.util.ObjectUtils;
081import org.springframework.util.ReflectionUtils;
082import org.springframework.util.StringValueResolver;
083
084/**
085 * Abstract implementation of the {@link org.springframework.context.ApplicationContext}
086 * interface. Doesn't mandate the type of storage used for configuration; simply
087 * implements common context functionality. Uses the Template Method design pattern,
088 * requiring concrete subclasses to implement abstract methods.
089 *
090 * <p>In contrast to a plain BeanFactory, an ApplicationContext is supposed
091 * to detect special beans defined in its internal bean factory:
092 * Therefore, this class automatically registers
093 * {@link org.springframework.beans.factory.config.BeanFactoryPostProcessor BeanFactoryPostProcessors},
094 * {@link org.springframework.beans.factory.config.BeanPostProcessor BeanPostProcessors},
095 * and {@link org.springframework.context.ApplicationListener ApplicationListeners}
096 * which are defined as beans in the context.
097 *
098 * <p>A {@link org.springframework.context.MessageSource} may also be supplied
099 * as a bean in the context, with the name "messageSource"; otherwise, message
100 * resolution is delegated to the parent context. Furthermore, a multicaster
101 * for application events can be supplied as an "applicationEventMulticaster" bean
102 * of type {@link org.springframework.context.event.ApplicationEventMulticaster}
103 * in the context; otherwise, a default multicaster of type
104 * {@link org.springframework.context.event.SimpleApplicationEventMulticaster} will be used.
105 *
106 * <p>Implements resource loading by extending
107 * {@link org.springframework.core.io.DefaultResourceLoader}.
108 * Consequently treats non-URL resource paths as class path resources
109 * (supporting full class path resource names that include the package path,
110 * e.g. "mypackage/myresource.dat"), unless the {@link #getResourceByPath}
111 * method is overridden in a subclass.
112 *
113 * @author Rod Johnson
114 * @author Juergen Hoeller
115 * @author Mark Fisher
116 * @author Stephane Nicoll
117 * @since January 21, 2001
118 * @see #refreshBeanFactory
119 * @see #getBeanFactory
120 * @see org.springframework.beans.factory.config.BeanFactoryPostProcessor
121 * @see org.springframework.beans.factory.config.BeanPostProcessor
122 * @see org.springframework.context.event.ApplicationEventMulticaster
123 * @see org.springframework.context.ApplicationListener
124 * @see org.springframework.context.MessageSource
125 */
126public abstract class AbstractApplicationContext extends DefaultResourceLoader
127                implements ConfigurableApplicationContext, DisposableBean {
128
129        /**
130         * Name of the MessageSource bean in the factory.
131         * If none is supplied, message resolution is delegated to the parent.
132         * @see MessageSource
133         */
134        public static final String MESSAGE_SOURCE_BEAN_NAME = "messageSource";
135
136        /**
137         * Name of the LifecycleProcessor bean in the factory.
138         * If none is supplied, a DefaultLifecycleProcessor is used.
139         * @see org.springframework.context.LifecycleProcessor
140         * @see org.springframework.context.support.DefaultLifecycleProcessor
141         */
142        public static final String LIFECYCLE_PROCESSOR_BEAN_NAME = "lifecycleProcessor";
143
144        /**
145         * Name of the ApplicationEventMulticaster bean in the factory.
146         * If none is supplied, a default SimpleApplicationEventMulticaster is used.
147         * @see org.springframework.context.event.ApplicationEventMulticaster
148         * @see org.springframework.context.event.SimpleApplicationEventMulticaster
149         */
150        public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";
151
152
153        static {
154                // Eagerly load the ContextClosedEvent class to avoid weird classloader issues
155                // on application shutdown in WebLogic 8.1. (Reported by Dustin Woods.)
156                ContextClosedEvent.class.getName();
157        }
158
159
160        /** Logger used by this class. Available to subclasses. */
161        protected final Log logger = LogFactory.getLog(getClass());
162
163        /** Unique id for this context, if any */
164        private String id = ObjectUtils.identityToString(this);
165
166        /** Display name */
167        private String displayName = ObjectUtils.identityToString(this);
168
169        /** Parent context */
170        private ApplicationContext parent;
171
172        /** Environment used by this context */
173        private ConfigurableEnvironment environment;
174
175        /** BeanFactoryPostProcessors to apply on refresh */
176        private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors =
177                        new ArrayList<BeanFactoryPostProcessor>();
178
179        /** System time in milliseconds when this context started */
180        private long startupDate;
181
182        /** Flag that indicates whether this context is currently active */
183        private final AtomicBoolean active = new AtomicBoolean();
184
185        /** Flag that indicates whether this context has been closed already */
186        private final AtomicBoolean closed = new AtomicBoolean();
187
188        /** Synchronization monitor for the "refresh" and "destroy" */
189        private final Object startupShutdownMonitor = new Object();
190
191        /** Reference to the JVM shutdown hook, if registered */
192        private Thread shutdownHook;
193
194        /** ResourcePatternResolver used by this context */
195        private ResourcePatternResolver resourcePatternResolver;
196
197        /** LifecycleProcessor for managing the lifecycle of beans within this context */
198        private LifecycleProcessor lifecycleProcessor;
199
200        /** MessageSource we delegate our implementation of this interface to */
201        private MessageSource messageSource;
202
203        /** Helper class used in event publishing */
204        private ApplicationEventMulticaster applicationEventMulticaster;
205
206        /** Statically specified listeners */
207        private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<ApplicationListener<?>>();
208
209        /** ApplicationEvents published early */
210        private Set<ApplicationEvent> earlyApplicationEvents;
211
212
213        /**
214         * Create a new AbstractApplicationContext with no parent.
215         */
216        public AbstractApplicationContext() {
217                this.resourcePatternResolver = getResourcePatternResolver();
218        }
219
220        /**
221         * Create a new AbstractApplicationContext with the given parent context.
222         * @param parent the parent context
223         */
224        public AbstractApplicationContext(ApplicationContext parent) {
225                this();
226                setParent(parent);
227        }
228
229
230        //---------------------------------------------------------------------
231        // Implementation of ApplicationContext interface
232        //---------------------------------------------------------------------
233
234        /**
235         * Set the unique id of this application context.
236         * <p>Default is the object id of the context instance, or the name
237         * of the context bean if the context is itself defined as a bean.
238         * @param id the unique id of the context
239         */
240        @Override
241        public void setId(String id) {
242                this.id = id;
243        }
244
245        @Override
246        public String getId() {
247                return this.id;
248        }
249
250        @Override
251        public String getApplicationName() {
252                return "";
253        }
254
255        /**
256         * Set a friendly name for this context.
257         * Typically done during initialization of concrete context implementations.
258         * <p>Default is the object id of the context instance.
259         */
260        public void setDisplayName(String displayName) {
261                Assert.hasLength(displayName, "Display name must not be empty");
262                this.displayName = displayName;
263        }
264
265        /**
266         * Return a friendly name for this context.
267         * @return a display name for this context (never {@code null})
268         */
269        @Override
270        public String getDisplayName() {
271                return this.displayName;
272        }
273
274        /**
275         * Return the parent context, or {@code null} if there is no parent
276         * (that is, this context is the root of the context hierarchy).
277         */
278        @Override
279        public ApplicationContext getParent() {
280                return this.parent;
281        }
282
283        /**
284         * Set the {@code Environment} for this application context.
285         * <p>Default value is determined by {@link #createEnvironment()}. Replacing the
286         * default with this method is one option but configuration through {@link
287         * #getEnvironment()} should also be considered. In either case, such modifications
288         * should be performed <em>before</em> {@link #refresh()}.
289         * @see org.springframework.context.support.AbstractApplicationContext#createEnvironment
290         */
291        @Override
292        public void setEnvironment(ConfigurableEnvironment environment) {
293                this.environment = environment;
294        }
295
296        /**
297         * Return the {@code Environment} for this application context in configurable
298         * form, allowing for further customization.
299         * <p>If none specified, a default environment will be initialized via
300         * {@link #createEnvironment()}.
301         */
302        @Override
303        public ConfigurableEnvironment getEnvironment() {
304                if (this.environment == null) {
305                        this.environment = createEnvironment();
306                }
307                return this.environment;
308        }
309
310        /**
311         * Create and return a new {@link StandardEnvironment}.
312         * <p>Subclasses may override this method in order to supply
313         * a custom {@link ConfigurableEnvironment} implementation.
314         */
315        protected ConfigurableEnvironment createEnvironment() {
316                return new StandardEnvironment();
317        }
318
319        /**
320         * Return this context's internal bean factory as AutowireCapableBeanFactory,
321         * if already available.
322         * @see #getBeanFactory()
323         */
324        @Override
325        public AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException {
326                return getBeanFactory();
327        }
328
329        /**
330         * Return the timestamp (ms) when this context was first loaded.
331         */
332        @Override
333        public long getStartupDate() {
334                return this.startupDate;
335        }
336
337        /**
338         * Publish the given event to all listeners.
339         * <p>Note: Listeners get initialized after the MessageSource, to be able
340         * to access it within listener implementations. Thus, MessageSource
341         * implementations cannot publish events.
342         * @param event the event to publish (may be application-specific or a
343         * standard framework event)
344         */
345        @Override
346        public void publishEvent(ApplicationEvent event) {
347                publishEvent(event, null);
348        }
349
350        /**
351         * Publish the given event to all listeners.
352         * <p>Note: Listeners get initialized after the MessageSource, to be able
353         * to access it within listener implementations. Thus, MessageSource
354         * implementations cannot publish events.
355         * @param event the event to publish (may be an {@link ApplicationEvent}
356         * or a payload object to be turned into a {@link PayloadApplicationEvent})
357         */
358        @Override
359        public void publishEvent(Object event) {
360                publishEvent(event, null);
361        }
362
363        /**
364         * Publish the given event to all listeners.
365         * @param event the event to publish (may be an {@link ApplicationEvent}
366         * or a payload object to be turned into a {@link PayloadApplicationEvent})
367         * @param eventType the resolved event type, if known
368         * @since 4.2
369         */
370        protected void publishEvent(Object event, ResolvableType eventType) {
371                Assert.notNull(event, "Event must not be null");
372                if (logger.isTraceEnabled()) {
373                        logger.trace("Publishing event in " + getDisplayName() + ": " + event);
374                }
375
376                // Decorate event as an ApplicationEvent if necessary
377                ApplicationEvent applicationEvent;
378                if (event instanceof ApplicationEvent) {
379                        applicationEvent = (ApplicationEvent) event;
380                }
381                else {
382                        applicationEvent = new PayloadApplicationEvent<Object>(this, event);
383                        if (eventType == null) {
384                                eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
385                        }
386                }
387
388                // Multicast right now if possible - or lazily once the multicaster is initialized
389                if (this.earlyApplicationEvents != null) {
390                        this.earlyApplicationEvents.add(applicationEvent);
391                }
392                else {
393                        getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
394                }
395
396                // Publish event via parent context as well...
397                if (this.parent != null) {
398                        if (this.parent instanceof AbstractApplicationContext) {
399                                ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
400                        }
401                        else {
402                                this.parent.publishEvent(event);
403                        }
404                }
405        }
406
407        /**
408         * Return the internal ApplicationEventMulticaster used by the context.
409         * @return the internal ApplicationEventMulticaster (never {@code null})
410         * @throws IllegalStateException if the context has not been initialized yet
411         */
412        ApplicationEventMulticaster getApplicationEventMulticaster() throws IllegalStateException {
413                if (this.applicationEventMulticaster == null) {
414                        throw new IllegalStateException("ApplicationEventMulticaster not initialized - " +
415                                        "call 'refresh' before multicasting events via the context: " + this);
416                }
417                return this.applicationEventMulticaster;
418        }
419
420        /**
421         * Return the internal LifecycleProcessor used by the context.
422         * @return the internal LifecycleProcessor (never {@code null})
423         * @throws IllegalStateException if the context has not been initialized yet
424         */
425        LifecycleProcessor getLifecycleProcessor() throws IllegalStateException {
426                if (this.lifecycleProcessor == null) {
427                        throw new IllegalStateException("LifecycleProcessor not initialized - " +
428                                        "call 'refresh' before invoking lifecycle methods via the context: " + this);
429                }
430                return this.lifecycleProcessor;
431        }
432
433        /**
434         * Return the ResourcePatternResolver to use for resolving location patterns
435         * into Resource instances. Default is a
436         * {@link org.springframework.core.io.support.PathMatchingResourcePatternResolver},
437         * supporting Ant-style location patterns.
438         * <p>Can be overridden in subclasses, for extended resolution strategies,
439         * for example in a web environment.
440         * <p><b>Do not call this when needing to resolve a location pattern.</b>
441         * Call the context's {@code getResources} method instead, which
442         * will delegate to the ResourcePatternResolver.
443         * @return the ResourcePatternResolver for this context
444         * @see #getResources
445         * @see org.springframework.core.io.support.PathMatchingResourcePatternResolver
446         */
447        protected ResourcePatternResolver getResourcePatternResolver() {
448                return new PathMatchingResourcePatternResolver(this);
449        }
450
451
452        //---------------------------------------------------------------------
453        // Implementation of ConfigurableApplicationContext interface
454        //---------------------------------------------------------------------
455
456        /**
457         * Set the parent of this application context.
458         * <p>The parent {@linkplain ApplicationContext#getEnvironment() environment} is
459         * {@linkplain ConfigurableEnvironment#merge(ConfigurableEnvironment) merged} with
460         * this (child) application context environment if the parent is non-{@code null} and
461         * its environment is an instance of {@link ConfigurableEnvironment}.
462         * @see ConfigurableEnvironment#merge(ConfigurableEnvironment)
463         */
464        @Override
465        public void setParent(ApplicationContext parent) {
466                this.parent = parent;
467                if (parent != null) {
468                        Environment parentEnvironment = parent.getEnvironment();
469                        if (parentEnvironment instanceof ConfigurableEnvironment) {
470                                getEnvironment().merge((ConfigurableEnvironment) parentEnvironment);
471                        }
472                }
473        }
474
475        @Override
476        public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor) {
477                Assert.notNull(postProcessor, "BeanFactoryPostProcessor must not be null");
478                this.beanFactoryPostProcessors.add(postProcessor);
479        }
480
481        /**
482         * Return the list of BeanFactoryPostProcessors that will get applied
483         * to the internal BeanFactory.
484         */
485        public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
486                return this.beanFactoryPostProcessors;
487        }
488
489        @Override
490        public void addApplicationListener(ApplicationListener<?> listener) {
491                Assert.notNull(listener, "ApplicationListener must not be null");
492                if (this.applicationEventMulticaster != null) {
493                        this.applicationEventMulticaster.addApplicationListener(listener);
494                }
495                else {
496                        this.applicationListeners.add(listener);
497                }
498        }
499
500        /**
501         * Return the list of statically specified ApplicationListeners.
502         */
503        public Collection<ApplicationListener<?>> getApplicationListeners() {
504                return this.applicationListeners;
505        }
506
507        @Override
508        public void refresh() throws BeansException, IllegalStateException {
509                synchronized (this.startupShutdownMonitor) {
510                        // Prepare this context for refreshing.
511                        prepareRefresh();
512
513                        // Tell the subclass to refresh the internal bean factory.
514                        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
515
516                        // Prepare the bean factory for use in this context.
517                        prepareBeanFactory(beanFactory);
518
519                        try {
520                                // Allows post-processing of the bean factory in context subclasses.
521                                postProcessBeanFactory(beanFactory);
522
523                                // Invoke factory processors registered as beans in the context.
524                                invokeBeanFactoryPostProcessors(beanFactory);
525
526                                // Register bean processors that intercept bean creation.
527                                registerBeanPostProcessors(beanFactory);
528
529                                // Initialize message source for this context.
530                                initMessageSource();
531
532                                // Initialize event multicaster for this context.
533                                initApplicationEventMulticaster();
534
535                                // Initialize other special beans in specific context subclasses.
536                                onRefresh();
537
538                                // Check for listener beans and register them.
539                                registerListeners();
540
541                                // Instantiate all remaining (non-lazy-init) singletons.
542                                finishBeanFactoryInitialization(beanFactory);
543
544                                // Last step: publish corresponding event.
545                                finishRefresh();
546                        }
547
548                        catch (BeansException ex) {
549                                if (logger.isWarnEnabled()) {
550                                        logger.warn("Exception encountered during context initialization - " +
551                                                        "cancelling refresh attempt: " + ex);
552                                }
553
554                                // Destroy already created singletons to avoid dangling resources.
555                                destroyBeans();
556
557                                // Reset 'active' flag.
558                                cancelRefresh(ex);
559
560                                // Propagate exception to caller.
561                                throw ex;
562                        }
563
564                        finally {
565                                // Reset common introspection caches in Spring's core, since we
566                                // might not ever need metadata for singleton beans anymore...
567                                resetCommonCaches();
568                        }
569                }
570        }
571
572        /**
573         * Prepare this context for refreshing, setting its startup date and
574         * active flag as well as performing any initialization of property sources.
575         */
576        protected void prepareRefresh() {
577                // Switch to active.
578                this.startupDate = System.currentTimeMillis();
579                this.closed.set(false);
580                this.active.set(true);
581
582                if (logger.isInfoEnabled()) {
583                        logger.info("Refreshing " + this);
584                }
585
586                // Initialize any placeholder property sources in the context environment.
587                initPropertySources();
588
589                // Validate that all properties marked as required are resolvable:
590                // see ConfigurablePropertyResolver#setRequiredProperties
591                getEnvironment().validateRequiredProperties();
592
593                // Allow for the collection of early ApplicationEvents,
594                // to be published once the multicaster is available...
595                this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
596        }
597
598        /**
599         * <p>Replace any stub property sources with actual instances.
600         * @see org.springframework.core.env.PropertySource.StubPropertySource
601         * @see org.springframework.web.context.support.WebApplicationContextUtils#initServletPropertySources
602         */
603        protected void initPropertySources() {
604                // For subclasses: do nothing by default.
605        }
606
607        /**
608         * Tell the subclass to refresh the internal bean factory.
609         * @return the fresh BeanFactory instance
610         * @see #refreshBeanFactory()
611         * @see #getBeanFactory()
612         */
613        protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
614                refreshBeanFactory();
615                ConfigurableListableBeanFactory beanFactory = getBeanFactory();
616                if (logger.isDebugEnabled()) {
617                        logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
618                }
619                return beanFactory;
620        }
621
622        /**
623         * Configure the factory's standard context characteristics,
624         * such as the context's ClassLoader and post-processors.
625         * @param beanFactory the BeanFactory to configure
626         */
627        protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
628                // Tell the internal bean factory to use the context's class loader etc.
629                beanFactory.setBeanClassLoader(getClassLoader());
630                beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
631                beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
632
633                // Configure the bean factory with context callbacks.
634                beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
635                beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
636                beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
637                beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
638                beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
639                beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
640                beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
641
642                // BeanFactory interface not registered as resolvable type in a plain factory.
643                // MessageSource registered (and found for autowiring) as a bean.
644                beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
645                beanFactory.registerResolvableDependency(ResourceLoader.class, this);
646                beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
647                beanFactory.registerResolvableDependency(ApplicationContext.class, this);
648
649                // Register early post-processor for detecting inner beans as ApplicationListeners.
650                beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
651
652                // Detect a LoadTimeWeaver and prepare for weaving, if found.
653                if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
654                        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
655                        // Set a temporary ClassLoader for type matching.
656                        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
657                }
658
659                // Register default environment beans.
660                if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
661                        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
662                }
663                if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
664                        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
665                }
666                if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
667                        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
668                }
669        }
670
671        /**
672         * Modify the application context's internal bean factory after its standard
673         * initialization. All bean definitions will have been loaded, but no beans
674         * will have been instantiated yet. This allows for registering special
675         * BeanPostProcessors etc in certain ApplicationContext implementations.
676         * @param beanFactory the bean factory used by the application context
677         */
678        protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
679        }
680
681        /**
682         * Instantiate and invoke all registered BeanFactoryPostProcessor beans,
683         * respecting explicit order if given.
684         * <p>Must be called before singleton instantiation.
685         */
686        protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
687                PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
688
689                // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
690                // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
691                if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
692                        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
693                        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
694                }
695        }
696
697        /**
698         * Instantiate and register all BeanPostProcessor beans,
699         * respecting explicit order if given.
700         * <p>Must be called before any instantiation of application beans.
701         */
702        protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
703                PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
704        }
705
706        /**
707         * Initialize the MessageSource.
708         * Use parent's if none defined in this context.
709         */
710        protected void initMessageSource() {
711                ConfigurableListableBeanFactory beanFactory = getBeanFactory();
712                if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
713                        this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
714                        // Make MessageSource aware of parent MessageSource.
715                        if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
716                                HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
717                                if (hms.getParentMessageSource() == null) {
718                                        // Only set parent context as parent MessageSource if no parent MessageSource
719                                        // registered already.
720                                        hms.setParentMessageSource(getInternalParentMessageSource());
721                                }
722                        }
723                        if (logger.isDebugEnabled()) {
724                                logger.debug("Using MessageSource [" + this.messageSource + "]");
725                        }
726                }
727                else {
728                        // Use empty MessageSource to be able to accept getMessage calls.
729                        DelegatingMessageSource dms = new DelegatingMessageSource();
730                        dms.setParentMessageSource(getInternalParentMessageSource());
731                        this.messageSource = dms;
732                        beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
733                        if (logger.isDebugEnabled()) {
734                                logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME +
735                                                "': using default [" + this.messageSource + "]");
736                        }
737                }
738        }
739
740        /**
741         * Initialize the ApplicationEventMulticaster.
742         * Uses SimpleApplicationEventMulticaster if none defined in the context.
743         * @see org.springframework.context.event.SimpleApplicationEventMulticaster
744         */
745        protected void initApplicationEventMulticaster() {
746                ConfigurableListableBeanFactory beanFactory = getBeanFactory();
747                if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
748                        this.applicationEventMulticaster =
749                                        beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
750                        if (logger.isDebugEnabled()) {
751                                logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
752                        }
753                }
754                else {
755                        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
756                        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
757                        if (logger.isDebugEnabled()) {
758                                logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
759                                                APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
760                                                "': using default [" + this.applicationEventMulticaster + "]");
761                        }
762                }
763        }
764
765        /**
766         * Initialize the LifecycleProcessor.
767         * Uses DefaultLifecycleProcessor if none defined in the context.
768         * @see org.springframework.context.support.DefaultLifecycleProcessor
769         */
770        protected void initLifecycleProcessor() {
771                ConfigurableListableBeanFactory beanFactory = getBeanFactory();
772                if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
773                        this.lifecycleProcessor =
774                                        beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
775                        if (logger.isDebugEnabled()) {
776                                logger.debug("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
777                        }
778                }
779                else {
780                        DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
781                        defaultProcessor.setBeanFactory(beanFactory);
782                        this.lifecycleProcessor = defaultProcessor;
783                        beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
784                        if (logger.isDebugEnabled()) {
785                                logger.debug("Unable to locate LifecycleProcessor with name '" +
786                                                LIFECYCLE_PROCESSOR_BEAN_NAME +
787                                                "': using default [" + this.lifecycleProcessor + "]");
788                        }
789                }
790        }
791
792        /**
793         * Template method which can be overridden to add context-specific refresh work.
794         * Called on initialization of special beans, before instantiation of singletons.
795         * <p>This implementation is empty.
796         * @throws BeansException in case of errors
797         * @see #refresh()
798         */
799        protected void onRefresh() throws BeansException {
800                // For subclasses: do nothing by default.
801        }
802
803        /**
804         * Add beans that implement ApplicationListener as listeners.
805         * Doesn't affect other listeners, which can be added without being beans.
806         */
807        protected void registerListeners() {
808                // Register statically specified listeners first.
809                for (ApplicationListener<?> listener : getApplicationListeners()) {
810                        getApplicationEventMulticaster().addApplicationListener(listener);
811                }
812
813                // Do not initialize FactoryBeans here: We need to leave all regular beans
814                // uninitialized to let post-processors apply to them!
815                String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
816                for (String listenerBeanName : listenerBeanNames) {
817                        getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
818                }
819
820                // Publish early application events now that we finally have a multicaster...
821                Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
822                this.earlyApplicationEvents = null;
823                if (earlyEventsToProcess != null) {
824                        for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
825                                getApplicationEventMulticaster().multicastEvent(earlyEvent);
826                        }
827                }
828        }
829
830        /**
831         * Finish the initialization of this context's bean factory,
832         * initializing all remaining singleton beans.
833         */
834        protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
835                // Initialize conversion service for this context.
836                if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
837                                beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
838                        beanFactory.setConversionService(
839                                        beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
840                }
841
842                // Register a default embedded value resolver if no bean post-processor
843                // (such as a PropertyPlaceholderConfigurer bean) registered any before:
844                // at this point, primarily for resolution in annotation attribute values.
845                if (!beanFactory.hasEmbeddedValueResolver()) {
846                        beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
847                                @Override
848                                public String resolveStringValue(String strVal) {
849                                        return getEnvironment().resolvePlaceholders(strVal);
850                                }
851                        });
852                }
853
854                // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
855                String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
856                for (String weaverAwareName : weaverAwareNames) {
857                        getBean(weaverAwareName);
858                }
859
860                // Stop using the temporary ClassLoader for type matching.
861                beanFactory.setTempClassLoader(null);
862
863                // Allow for caching all bean definition metadata, not expecting further changes.
864                beanFactory.freezeConfiguration();
865
866                // Instantiate all remaining (non-lazy-init) singletons.
867                beanFactory.preInstantiateSingletons();
868        }
869
870        /**
871         * Finish the refresh of this context, invoking the LifecycleProcessor's
872         * onRefresh() method and publishing the
873         * {@link org.springframework.context.event.ContextRefreshedEvent}.
874         */
875        protected void finishRefresh() {
876                // Initialize lifecycle processor for this context.
877                initLifecycleProcessor();
878
879                // Propagate refresh to lifecycle processor first.
880                getLifecycleProcessor().onRefresh();
881
882                // Publish the final event.
883                publishEvent(new ContextRefreshedEvent(this));
884
885                // Participate in LiveBeansView MBean, if active.
886                LiveBeansView.registerApplicationContext(this);
887        }
888
889        /**
890         * Cancel this context's refresh attempt, resetting the {@code active} flag
891         * after an exception got thrown.
892         * @param ex the exception that led to the cancellation
893         */
894        protected void cancelRefresh(BeansException ex) {
895                this.active.set(false);
896        }
897
898        /**
899         * Reset Spring's common core caches, in particular the {@link ReflectionUtils},
900         * {@link ResolvableType} and {@link CachedIntrospectionResults} caches.
901         * @since 4.2
902         * @see ReflectionUtils#clearCache()
903         * @see ResolvableType#clearCache()
904         * @see CachedIntrospectionResults#clearClassLoader(ClassLoader)
905         */
906        protected void resetCommonCaches() {
907                ReflectionUtils.clearCache();
908                ResolvableType.clearCache();
909                CachedIntrospectionResults.clearClassLoader(getClassLoader());
910        }
911
912
913        /**
914         * Register a shutdown hook with the JVM runtime, closing this context
915         * on JVM shutdown unless it has already been closed at that time.
916         * <p>Delegates to {@code doClose()} for the actual closing procedure.
917         * @see Runtime#addShutdownHook
918         * @see #close()
919         * @see #doClose()
920         */
921        @Override
922        public void registerShutdownHook() {
923                if (this.shutdownHook == null) {
924                        // No shutdown hook registered yet.
925                        this.shutdownHook = new Thread() {
926                                @Override
927                                public void run() {
928                                        synchronized (startupShutdownMonitor) {
929                                                doClose();
930                                        }
931                                }
932                        };
933                        Runtime.getRuntime().addShutdownHook(this.shutdownHook);
934                }
935        }
936
937        /**
938         * DisposableBean callback for destruction of this instance.
939         * <p>The {@link #close()} method is the native way to shut down
940         * an ApplicationContext, which this method simply delegates to.
941         * @see #close()
942         */
943        @Override
944        public void destroy() {
945                close();
946        }
947
948        /**
949         * Close this application context, destroying all beans in its bean factory.
950         * <p>Delegates to {@code doClose()} for the actual closing procedure.
951         * Also removes a JVM shutdown hook, if registered, as it's not needed anymore.
952         * @see #doClose()
953         * @see #registerShutdownHook()
954         */
955        @Override
956        public void close() {
957                synchronized (this.startupShutdownMonitor) {
958                        doClose();
959                        // If we registered a JVM shutdown hook, we don't need it anymore now:
960                        // We've already explicitly closed the context.
961                        if (this.shutdownHook != null) {
962                                try {
963                                        Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
964                                }
965                                catch (IllegalStateException ex) {
966                                        // ignore - VM is already shutting down
967                                }
968                        }
969                }
970        }
971
972        /**
973         * Actually performs context closing: publishes a ContextClosedEvent and
974         * destroys the singletons in the bean factory of this application context.
975         * <p>Called by both {@code close()} and a JVM shutdown hook, if any.
976         * @see org.springframework.context.event.ContextClosedEvent
977         * @see #destroyBeans()
978         * @see #close()
979         * @see #registerShutdownHook()
980         */
981        protected void doClose() {
982                // Check whether an actual close attempt is necessary...
983                if (this.active.get() && this.closed.compareAndSet(false, true)) {
984                        if (logger.isInfoEnabled()) {
985                                logger.info("Closing " + this);
986                        }
987
988                        LiveBeansView.unregisterApplicationContext(this);
989
990                        try {
991                                // Publish shutdown event.
992                                publishEvent(new ContextClosedEvent(this));
993                        }
994                        catch (Throwable ex) {
995                                logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
996                        }
997
998                        // Stop all Lifecycle beans, to avoid delays during individual destruction.
999                        if (this.lifecycleProcessor != null) {
1000                                try {
1001                                        this.lifecycleProcessor.onClose();
1002                                }
1003                                catch (Throwable ex) {
1004                                        logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
1005                                }
1006                        }
1007
1008                        // Destroy all cached singletons in the context's BeanFactory.
1009                        destroyBeans();
1010
1011                        // Close the state of this context itself.
1012                        closeBeanFactory();
1013
1014                        // Let subclasses do some final clean-up if they wish...
1015                        onClose();
1016
1017                        // Switch to inactive.
1018                        this.active.set(false);
1019                }
1020        }
1021
1022        /**
1023         * Template method for destroying all beans that this context manages.
1024         * The default implementation destroy all cached singletons in this context,
1025         * invoking {@code DisposableBean.destroy()} and/or the specified
1026         * "destroy-method".
1027         * <p>Can be overridden to add context-specific bean destruction steps
1028         * right before or right after standard singleton destruction,
1029         * while the context's BeanFactory is still active.
1030         * @see #getBeanFactory()
1031         * @see org.springframework.beans.factory.config.ConfigurableBeanFactory#destroySingletons()
1032         */
1033        protected void destroyBeans() {
1034                getBeanFactory().destroySingletons();
1035        }
1036
1037        /**
1038         * Template method which can be overridden to add context-specific shutdown work.
1039         * The default implementation is empty.
1040         * <p>Called at the end of {@link #doClose}'s shutdown procedure, after
1041         * this context's BeanFactory has been closed. If custom shutdown logic
1042         * needs to execute while the BeanFactory is still active, override
1043         * the {@link #destroyBeans()} method instead.
1044         */
1045        protected void onClose() {
1046                // For subclasses: do nothing by default.
1047        }
1048
1049        @Override
1050        public boolean isActive() {
1051                return this.active.get();
1052        }
1053
1054        /**
1055         * Assert that this context's BeanFactory is currently active,
1056         * throwing an {@link IllegalStateException} if it isn't.
1057         * <p>Invoked by all {@link BeanFactory} delegation methods that depend
1058         * on an active context, i.e. in particular all bean accessor methods.
1059         * <p>The default implementation checks the {@link #isActive() 'active'} status
1060         * of this context overall. May be overridden for more specific checks, or for a
1061         * no-op if {@link #getBeanFactory()} itself throws an exception in such a case.
1062         */
1063        protected void assertBeanFactoryActive() {
1064                if (!this.active.get()) {
1065                        if (this.closed.get()) {
1066                                throw new IllegalStateException(getDisplayName() + " has been closed already");
1067                        }
1068                        else {
1069                                throw new IllegalStateException(getDisplayName() + " has not been refreshed yet");
1070                        }
1071                }
1072        }
1073
1074
1075        //---------------------------------------------------------------------
1076        // Implementation of BeanFactory interface
1077        //---------------------------------------------------------------------
1078
1079        @Override
1080        public Object getBean(String name) throws BeansException {
1081                assertBeanFactoryActive();
1082                return getBeanFactory().getBean(name);
1083        }
1084
1085        @Override
1086        public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
1087                assertBeanFactoryActive();
1088                return getBeanFactory().getBean(name, requiredType);
1089        }
1090
1091        @Override
1092        public <T> T getBean(Class<T> requiredType) throws BeansException {
1093                assertBeanFactoryActive();
1094                return getBeanFactory().getBean(requiredType);
1095        }
1096
1097        @Override
1098        public Object getBean(String name, Object... args) throws BeansException {
1099                assertBeanFactoryActive();
1100                return getBeanFactory().getBean(name, args);
1101        }
1102
1103        @Override
1104        public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
1105                assertBeanFactoryActive();
1106                return getBeanFactory().getBean(requiredType, args);
1107        }
1108
1109        @Override
1110        public boolean containsBean(String name) {
1111                return getBeanFactory().containsBean(name);
1112        }
1113
1114        @Override
1115        public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
1116                assertBeanFactoryActive();
1117                return getBeanFactory().isSingleton(name);
1118        }
1119
1120        @Override
1121        public boolean isPrototype(String name) throws NoSuchBeanDefinitionException {
1122                assertBeanFactoryActive();
1123                return getBeanFactory().isPrototype(name);
1124        }
1125
1126        @Override
1127        public boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException {
1128                assertBeanFactoryActive();
1129                return getBeanFactory().isTypeMatch(name, typeToMatch);
1130        }
1131
1132        @Override
1133        public boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException {
1134                assertBeanFactoryActive();
1135                return getBeanFactory().isTypeMatch(name, typeToMatch);
1136        }
1137
1138        @Override
1139        public Class<?> getType(String name) throws NoSuchBeanDefinitionException {
1140                assertBeanFactoryActive();
1141                return getBeanFactory().getType(name);
1142        }
1143
1144        @Override
1145        public String[] getAliases(String name) {
1146                return getBeanFactory().getAliases(name);
1147        }
1148
1149
1150        //---------------------------------------------------------------------
1151        // Implementation of ListableBeanFactory interface
1152        //---------------------------------------------------------------------
1153
1154        @Override
1155        public boolean containsBeanDefinition(String beanName) {
1156                return getBeanFactory().containsBeanDefinition(beanName);
1157        }
1158
1159        @Override
1160        public int getBeanDefinitionCount() {
1161                return getBeanFactory().getBeanDefinitionCount();
1162        }
1163
1164        @Override
1165        public String[] getBeanDefinitionNames() {
1166                return getBeanFactory().getBeanDefinitionNames();
1167        }
1168
1169        @Override
1170        public String[] getBeanNamesForType(ResolvableType type) {
1171                assertBeanFactoryActive();
1172                return getBeanFactory().getBeanNamesForType(type);
1173        }
1174
1175        @Override
1176        public String[] getBeanNamesForType(Class<?> type) {
1177                assertBeanFactoryActive();
1178                return getBeanFactory().getBeanNamesForType(type);
1179        }
1180
1181        @Override
1182        public String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
1183                assertBeanFactoryActive();
1184                return getBeanFactory().getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
1185        }
1186
1187        @Override
1188        public <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException {
1189                assertBeanFactoryActive();
1190                return getBeanFactory().getBeansOfType(type);
1191        }
1192
1193        @Override
1194        public <T> Map<String, T> getBeansOfType(Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
1195                        throws BeansException {
1196
1197                assertBeanFactoryActive();
1198                return getBeanFactory().getBeansOfType(type, includeNonSingletons, allowEagerInit);
1199        }
1200
1201        @Override
1202        public String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType) {
1203                assertBeanFactoryActive();
1204                return getBeanFactory().getBeanNamesForAnnotation(annotationType);
1205        }
1206
1207        @Override
1208        public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType)
1209                        throws BeansException {
1210
1211                assertBeanFactoryActive();
1212                return getBeanFactory().getBeansWithAnnotation(annotationType);
1213        }
1214
1215        @Override
1216        public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
1217                        throws NoSuchBeanDefinitionException {
1218
1219                assertBeanFactoryActive();
1220                return getBeanFactory().findAnnotationOnBean(beanName, annotationType);
1221        }
1222
1223
1224        //---------------------------------------------------------------------
1225        // Implementation of HierarchicalBeanFactory interface
1226        //---------------------------------------------------------------------
1227
1228        @Override
1229        public BeanFactory getParentBeanFactory() {
1230                return getParent();
1231        }
1232
1233        @Override
1234        public boolean containsLocalBean(String name) {
1235                return getBeanFactory().containsLocalBean(name);
1236        }
1237
1238        /**
1239         * Return the internal bean factory of the parent context if it implements
1240         * ConfigurableApplicationContext; else, return the parent context itself.
1241         * @see org.springframework.context.ConfigurableApplicationContext#getBeanFactory
1242         */
1243        protected BeanFactory getInternalParentBeanFactory() {
1244                return (getParent() instanceof ConfigurableApplicationContext) ?
1245                                ((ConfigurableApplicationContext) getParent()).getBeanFactory() : getParent();
1246        }
1247
1248
1249        //---------------------------------------------------------------------
1250        // Implementation of MessageSource interface
1251        //---------------------------------------------------------------------
1252
1253        @Override
1254        public String getMessage(String code, Object[] args, String defaultMessage, Locale locale) {
1255                return getMessageSource().getMessage(code, args, defaultMessage, locale);
1256        }
1257
1258        @Override
1259        public String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException {
1260                return getMessageSource().getMessage(code, args, locale);
1261        }
1262
1263        @Override
1264        public String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException {
1265                return getMessageSource().getMessage(resolvable, locale);
1266        }
1267
1268        /**
1269         * Return the internal MessageSource used by the context.
1270         * @return the internal MessageSource (never {@code null})
1271         * @throws IllegalStateException if the context has not been initialized yet
1272         */
1273        private MessageSource getMessageSource() throws IllegalStateException {
1274                if (this.messageSource == null) {
1275                        throw new IllegalStateException("MessageSource not initialized - " +
1276                                        "call 'refresh' before accessing messages via the context: " + this);
1277                }
1278                return this.messageSource;
1279        }
1280
1281        /**
1282         * Return the internal message source of the parent context if it is an
1283         * AbstractApplicationContext too; else, return the parent context itself.
1284         */
1285        protected MessageSource getInternalParentMessageSource() {
1286                return (getParent() instanceof AbstractApplicationContext) ?
1287                        ((AbstractApplicationContext) getParent()).messageSource : getParent();
1288        }
1289
1290
1291        //---------------------------------------------------------------------
1292        // Implementation of ResourcePatternResolver interface
1293        //---------------------------------------------------------------------
1294
1295        @Override
1296        public Resource[] getResources(String locationPattern) throws IOException {
1297                return this.resourcePatternResolver.getResources(locationPattern);
1298        }
1299
1300
1301        //---------------------------------------------------------------------
1302        // Implementation of Lifecycle interface
1303        //---------------------------------------------------------------------
1304
1305        @Override
1306        public void start() {
1307                getLifecycleProcessor().start();
1308                publishEvent(new ContextStartedEvent(this));
1309        }
1310
1311        @Override
1312        public void stop() {
1313                getLifecycleProcessor().stop();
1314                publishEvent(new ContextStoppedEvent(this));
1315        }
1316
1317        @Override
1318        public boolean isRunning() {
1319                return (this.lifecycleProcessor != null && this.lifecycleProcessor.isRunning());
1320        }
1321
1322
1323        //---------------------------------------------------------------------
1324        // Abstract methods that must be implemented by subclasses
1325        //---------------------------------------------------------------------
1326
1327        /**
1328         * Subclasses must implement this method to perform the actual configuration load.
1329         * The method is invoked by {@link #refresh()} before any other initialization work.
1330         * <p>A subclass will either create a new bean factory and hold a reference to it,
1331         * or return a single BeanFactory instance that it holds. In the latter case, it will
1332         * usually throw an IllegalStateException if refreshing the context more than once.
1333         * @throws BeansException if initialization of the bean factory failed
1334         * @throws IllegalStateException if already initialized and multiple refresh
1335         * attempts are not supported
1336         */
1337        protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;
1338
1339        /**
1340         * Subclasses must implement this method to release their internal bean factory.
1341         * This method gets invoked by {@link #close()} after all other shutdown work.
1342         * <p>Should never throw an exception but rather log shutdown failures.
1343         */
1344        protected abstract void closeBeanFactory();
1345
1346        /**
1347         * Subclasses must return their internal bean factory here. They should implement the
1348         * lookup efficiently, so that it can be called repeatedly without a performance penalty.
1349         * <p>Note: Subclasses should check whether the context is still active before
1350         * returning the internal bean factory. The internal factory should generally be
1351         * considered unavailable once the context has been closed.
1352         * @return this application context's internal bean factory (never {@code null})
1353         * @throws IllegalStateException if the context does not hold an internal bean factory yet
1354         * (usually if {@link #refresh()} has never been called) or if the context has been
1355         * closed already
1356         * @see #refreshBeanFactory()
1357         * @see #closeBeanFactory()
1358         */
1359        @Override
1360        public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
1361
1362
1363        /**
1364         * Return information about this context.
1365         */
1366        @Override
1367        public String toString() {
1368                StringBuilder sb = new StringBuilder(getDisplayName());
1369                sb.append(": startup date [").append(new Date(getStartupDate()));
1370                sb.append("]; ");
1371                ApplicationContext parent = getParent();
1372                if (parent == null) {
1373                        sb.append("root of context hierarchy");
1374                }
1375                else {
1376                        sb.append("parent: ").append(parent.getDisplayName());
1377                }
1378                return sb.toString();
1379        }
1380
1381}