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