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}