• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

TAKETODAY / today-infrastructure / 16489896461

24 Jul 2025 06:51AM UTC coverage: 81.782%. Remained the same
16489896461

push

github

TAKETODAY
:sparkles: LogMessage API

59446 of 77637 branches covered (76.57%)

Branch coverage included in aggregate %.

140767 of 167176 relevant lines covered (84.2%)

3.6 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

82.04
today-context/src/main/java/infra/context/support/AbstractApplicationContext.java
1
/*
2
 * Copyright 2017 - 2025 the original author or authors.
3
 *
4
 * This program is free software: you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation, either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program. If not, see [https://www.gnu.org/licenses/]
16
 */
17

18
package infra.context.support;
19

20
import java.io.IOException;
21
import java.lang.annotation.Annotation;
22
import java.time.Duration;
23
import java.time.Instant;
24
import java.util.ArrayList;
25
import java.util.Collection;
26
import java.util.LinkedHashSet;
27
import java.util.List;
28
import java.util.Locale;
29
import java.util.Map;
30
import java.util.Set;
31
import java.util.concurrent.Executor;
32
import java.util.concurrent.atomic.AtomicBoolean;
33
import java.util.concurrent.locks.ReentrantLock;
34

35
import infra.beans.BeansException;
36
import infra.beans.CachedIntrospectionResults;
37
import infra.beans.factory.BeanFactory;
38
import infra.beans.factory.BeanFactoryInitializer;
39
import infra.beans.factory.BeanNotOfRequiredTypeException;
40
import infra.beans.factory.NoSuchBeanDefinitionException;
41
import infra.beans.factory.ObjectProvider;
42
import infra.beans.factory.config.AutowireCapableBeanFactory;
43
import infra.beans.factory.config.BeanDefinition;
44
import infra.beans.factory.config.BeanFactoryPostProcessor;
45
import infra.beans.factory.config.BeanPostProcessor;
46
import infra.beans.factory.config.ConfigurableBeanFactory;
47
import infra.beans.factory.config.ExpressionEvaluator;
48
import infra.beans.factory.support.DependencyInjector;
49
import infra.beans.factory.support.DependencyResolvingStrategies;
50
import infra.beans.factory.support.DependencyResolvingStrategy;
51
import infra.beans.support.ResourceEditorRegistrar;
52
import infra.context.ApplicationContext;
53
import infra.context.ApplicationContextAware;
54
import infra.context.ApplicationContextException;
55
import infra.context.ApplicationEvent;
56
import infra.context.ApplicationEventPublisher;
57
import infra.context.ApplicationEventPublisherAware;
58
import infra.context.ApplicationListener;
59
import infra.context.BootstrapContext;
60
import infra.context.BootstrapContextAware;
61
import infra.context.ConfigurableApplicationContext;
62
import infra.context.EnvironmentAware;
63
import infra.context.HierarchicalMessageSource;
64
import infra.context.LifecycleProcessor;
65
import infra.context.MessageSource;
66
import infra.context.MessageSourceAware;
67
import infra.context.MessageSourceResolvable;
68
import infra.context.NoSuchMessageException;
69
import infra.context.PayloadApplicationEvent;
70
import infra.context.ResourceLoaderAware;
71
import infra.context.event.ApplicationEventMulticaster;
72
import infra.context.event.ContextClosedEvent;
73
import infra.context.event.ContextRefreshedEvent;
74
import infra.context.event.ContextRestartedEvent;
75
import infra.context.event.ContextStartedEvent;
76
import infra.context.event.ContextStoppedEvent;
77
import infra.context.event.SimpleApplicationEventMulticaster;
78
import infra.context.expression.EmbeddedValueResolverAware;
79
import infra.context.expression.StandardBeanExpressionResolver;
80
import infra.context.weaving.LoadTimeWeaverAware;
81
import infra.context.weaving.LoadTimeWeaverAwareProcessor;
82
import infra.core.NativeDetector;
83
import infra.core.ResolvableType;
84
import infra.core.annotation.AnnotationUtils;
85
import infra.core.annotation.MergedAnnotation;
86
import infra.core.conversion.ConversionService;
87
import infra.core.env.ConfigurableEnvironment;
88
import infra.core.env.Environment;
89
import infra.core.env.StandardEnvironment;
90
import infra.core.io.DefaultResourceLoader;
91
import infra.core.io.PathMatchingPatternResourceLoader;
92
import infra.core.io.PatternResourceLoader;
93
import infra.core.io.Resource;
94
import infra.core.io.ResourceConsumer;
95
import infra.core.io.ResourceLoader;
96
import infra.core.io.SmartResourceConsumer;
97
import infra.lang.Assert;
98
import infra.lang.Nullable;
99
import infra.lang.TodayStrategies;
100
import infra.logging.Logger;
101
import infra.logging.LoggerFactory;
102
import infra.util.CollectionUtils;
103
import infra.util.ObjectUtils;
104
import infra.util.ReflectionUtils;
105

106
/**
107
 * Abstract implementation of the {@link infra.context.ApplicationContext}
108
 * interface. Doesn't mandate the type of storage used for configuration; simply
109
 * implements common context functionality. Uses the Template Method design pattern,
110
 * requiring concrete subclasses to implement abstract methods.
111
 *
112
 * <p>In contrast to a plain BeanFactory, an ApplicationContext is supposed
113
 * to detect special beans defined in its internal bean factory:
114
 * Therefore, this class automatically registers
115
 * {@link BeanFactoryPostProcessor BeanFactoryPostProcessors},
116
 * {@link BeanPostProcessor BeanPostProcessors},
117
 * and {@link infra.context.ApplicationListener ApplicationListeners}
118
 * which are defined as beans in the context.
119
 *
120
 * <p>A {@link infra.context.MessageSource} may also be supplied
121
 * as a bean in the context, with the name "messageSource"; otherwise, message
122
 * resolution is delegated to the parent context. Furthermore, a multicaster
123
 * for application events can be supplied as an "applicationEventMulticaster" bean
124
 * of type {@link ApplicationEventMulticaster}
125
 * in the context; otherwise, a default multicaster of type
126
 * {@link SimpleApplicationEventMulticaster} will be used.
127
 *
128
 * <p>Implements resource loading by extending
129
 * {@link DefaultResourceLoader}.
130
 * Consequently treats non-URL resource paths as class path resources
131
 * (supporting full class path resource names that include the package path,
132
 * e.g. "mypackage/myresource.dat"), unless the {@link #getResourceByPath}
133
 * method is overridden in a subclass.
134
 *
135
 * @author Rod Johnson
136
 * @author Juergen Hoeller
137
 * @author Mark Fisher
138
 * @author Stephane Nicoll
139
 * @author Sam Brannen
140
 * @author Sebastien Deleuze
141
 * @author Brian Clozel
142
 * @author <a href="https://github.com/TAKETODAY">Harry Yang</a>
143
 * @see #refreshBeanFactory
144
 * @see #getBeanFactory
145
 * @see BeanFactoryPostProcessor
146
 * @see BeanPostProcessor
147
 * @see ApplicationEventMulticaster
148
 * @see infra.context.ApplicationListener
149
 * @see infra.context.MessageSource
150
 * @since 2018-09-09 22:02
151
 */
152
@SuppressWarnings({ "unchecked" })
153
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
154

155
  protected final Logger logger = LoggerFactory.getLogger(getClass());
5✔
156

157
  /**
158
   * The name of the {@link LifecycleProcessor} bean in the context.
159
   * If none is supplied, a {@link DefaultLifecycleProcessor} is used.
160
   *
161
   * @see infra.context.LifecycleProcessor
162
   * @see DefaultLifecycleProcessor
163
   * @see #start()
164
   * @see #stop()
165
   */
166
  public static final String LIFECYCLE_PROCESSOR_BEAN_NAME = "lifecycleProcessor";
167

168
  /**
169
   * The name of the {@link MessageSource} bean in the context.
170
   * If none is supplied, message resolution is delegated to the parent.
171
   *
172
   * @see infra.context.MessageSource
173
   * @see ResourceBundleMessageSource
174
   * @see ReloadableResourceBundleMessageSource
175
   * @see #getMessage(MessageSourceResolvable, Locale)
176
   */
177
  public static final String MESSAGE_SOURCE_BEAN_NAME = "messageSource";
178

179
  /**
180
   * The name of the {@link ApplicationEventMulticaster} bean in the context.
181
   * If none is supplied, a {@link SimpleApplicationEventMulticaster} is used.
182
   *
183
   * @see ApplicationEventMulticaster
184
   * @see SimpleApplicationEventMulticaster
185
   * @see #publishEvent(ApplicationEvent)
186
   * @see #addApplicationListener(ApplicationListener)
187
   */
188
  public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";
189

190
  private Instant startupDate = Instant.now();
3✔
191

192
  @Nullable
193
  private ConfigurableEnvironment environment;
194

195
  // @since 2.1.5
196
  private State state = State.NONE;
3✔
197

198
  private final ArrayList<BeanFactoryPostProcessor> factoryPostProcessors = new ArrayList<>();
5✔
199

200
  /** Unique id for this context, if any. @since 4.0 */
201
  private String id = ObjectUtils.identityToString(this);
4✔
202

203
  /** Display name. */
204
  private String displayName = ObjectUtils.identityToString(this);
4✔
205

206
  /** Parent context. @since 4.0 */
207
  @Nullable
208
  private ApplicationContext parent;
209

210
  /** @since 4.0 */
211
  private final PatternResourceLoader patternResourceLoader = getPatternResourceLoader();
4✔
212

213
  /** @since 4.0 */
214

215
  @Nullable
216
  private ExpressionEvaluator expressionEvaluator;
217

218
  /** Reference to the JVM shutdown hook, if registered. */
219
  @Nullable
220
  private Thread shutdownHook;
221

222
  /** LifecycleProcessor for managing the lifecycle of beans within this context. @since 4.0 */
223
  @Nullable
224
  private LifecycleProcessor lifecycleProcessor;
225

226
  /** Helper class used in event publishing. @since 4.0 */
227
  @Nullable
228
  private ApplicationEventMulticaster applicationEventMulticaster;
229

230
  /** Statically specified listeners. @since 4.0 */
231
  private final LinkedHashSet<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();
5✔
232

233
  /** Local listeners registered before refresh. @since 4.0 */
234
  @Nullable
235
  private Set<ApplicationListener<?>> earlyApplicationListeners;
236

237
  /** ApplicationEvents published before the multicaster setup. @since 4.0 */
238
  @Nullable
239
  private Set<ApplicationEvent> earlyApplicationEvents;
240

241
  /** MessageSource we delegate our implementation of this interface to. @since 4.0 */
242
  @Nullable
243
  private MessageSource messageSource;
244

245
  @Nullable
246
  private BootstrapContext bootstrapContext;
247

248
  /** Flag that indicates whether this context is currently active. */
249
  private final AtomicBoolean active = new AtomicBoolean();
5✔
250

251
  /** Flag that indicates whether this context has been closed already. @since 4.0 */
252
  private final AtomicBoolean closed = new AtomicBoolean();
5✔
253

254
  /** Synchronization lock for "refresh" and "close". */
255
  private final ReentrantLock startupShutdownLock = new ReentrantLock();
5✔
256

257
  /** Currently active startup/shutdown thread. */
258
  @Nullable
259
  private volatile Thread startupShutdownThread;
260

261
  /**
262
   * Create a new AbstractApplicationContext with no parent.
263
   */
264
  public AbstractApplicationContext() { }
3✔
265

266
  /**
267
   * Create a new AbstractApplicationContext with the given parent context.
268
   *
269
   * @param parent the parent context
270
   */
271
  public AbstractApplicationContext(@Nullable ApplicationContext parent) {
272
    this();
2✔
273
    setParent(parent);
3✔
274
  }
1✔
275

276
  //---------------------------------------------------------------------
277
  // BootstrapContext @since 4.0
278
  //---------------------------------------------------------------------
279

280
  /**
281
   * Return the DefinitionLoadingContext to use for loading this context
282
   *
283
   * @return the DefinitionLoadingContext for this context
284
   * @since 4.0
285
   */
286
  protected BootstrapContext createBootstrapContext() {
287
    return new BootstrapContext(getBeanFactory(), this);
7✔
288
  }
289

290
  /**
291
   * set BootstrapContext
292
   *
293
   * @param bootstrapContext BootstrapContext
294
   * @since 4.0
295
   */
296
  public void setBootstrapContext(@Nullable BootstrapContext bootstrapContext) {
297
    this.bootstrapContext = bootstrapContext;
3✔
298
  }
1✔
299

300
  /**
301
   * Returns BootstrapContext
302
   *
303
   * @return Returns BootstrapContext
304
   * @since 4.0
305
   */
306
  @Override
307
  public BootstrapContext getBootstrapContext() {
308
    BootstrapContext bootstrapContext = this.bootstrapContext;
3✔
309
    if (bootstrapContext == null) {
2✔
310
      bootstrapContext = createBootstrapContext();
3✔
311
      this.bootstrapContext = bootstrapContext;
3✔
312
    }
313
    return bootstrapContext;
2✔
314
  }
315

316
  //---------------------------------------------------------------------
317
  // Implementation of PatternResourceLoader interface
318
  //---------------------------------------------------------------------
319

320
  @Override
321
  public Set<Resource> getResources(String locationPattern) throws IOException {
322
    return patternResourceLoader.getResources(locationPattern);
5✔
323
  }
324

325
  @Override
326
  public void scan(String locationPattern, ResourceConsumer consumer) throws IOException {
327
    patternResourceLoader.scan(locationPattern, consumer);
5✔
328
  }
1✔
329

330
  @Override
331
  public void scan(String locationPattern, SmartResourceConsumer consumer) throws IOException {
332
    patternResourceLoader.scan(locationPattern, consumer);
×
333
  }
×
334

335
  /**
336
   * Return the PatternResourceLoader to use for resolving location patterns
337
   * into Resource instances. Default is a {@link PathMatchingPatternResourceLoader},
338
   * supporting Ant-style location patterns.
339
   * <p>Can be overridden in subclasses, for extended resolution strategies,
340
   * for example in a web environment.
341
   * <p><b>Do not call this when needing to resolve a location pattern.</b>
342
   * Call the context's {@code getResources} method instead, which
343
   * will delegate to the PatternResourceLoader.
344
   *
345
   * @return the PatternResourceLoader for this context
346
   * @see #getResources
347
   * @see PathMatchingPatternResourceLoader
348
   */
349
  protected PatternResourceLoader getPatternResourceLoader() {
350
    return new PathMatchingPatternResourceLoader(this);
5✔
351
  }
352

353
  //---------------------------------------------------------------------
354
  // Implementation of ApplicationContext interface
355
  //---------------------------------------------------------------------
356

357
  /**
358
   * Set the unique id of this application context.
359
   * <p>Default is the object id of the context instance, or the name
360
   * of the context bean if the context is itself defined as a bean.
361
   *
362
   * @param id the unique id of the context
363
   */
364
  @Override
365
  public void setId(String id) {
366
    this.id = id;
3✔
367
  }
1✔
368

369
  @Override
370
  public String getId() {
371
    return this.id;
3✔
372
  }
373

374
  /**
375
   * Return this application name for this context.
376
   *
377
   * @return a display name for this context (never {@code null})
378
   */
379
  @Override
380
  public String getApplicationName() {
381
    return "";
2✔
382
  }
383

384
  /**
385
   * Set a friendly name for this context.
386
   * Typically done during initialization of concrete context implementations.
387
   * <p>Default is the object id of the context instance.
388
   *
389
   * @since 4.0
390
   */
391
  public void setDisplayName(String displayName) {
392
    Assert.hasLength(displayName, "Display name must not be empty");
3✔
393
    this.displayName = displayName;
3✔
394
  }
1✔
395

396
  /**
397
   * Return a friendly name for this context.
398
   *
399
   * @return a display name for this context (never {@code null})
400
   * @since 4.0
401
   */
402
  @Override
403
  public String getDisplayName() {
404
    return this.displayName;
3✔
405
  }
406

407
  /**
408
   * Return the parent context, or {@code null} if there is no parent
409
   * (that is, this context is the root of the context hierarchy).
410
   */
411
  @Override
412
  @Nullable
413
  public ApplicationContext getParent() {
414
    return this.parent;
3✔
415
  }
416

417
  @Override
418
  public AutowireCapableBeanFactory getAutowireCapableBeanFactory() {
419
    return getBeanFactory();
3✔
420
  }
421

422
  @Override
423
  public ExpressionEvaluator getExpressionEvaluator() {
424
    if (expressionEvaluator == null) {
3!
425
      expressionEvaluator = new ExpressionEvaluator(getBeanFactory());
7✔
426
    }
427
    return expressionEvaluator;
3✔
428
  }
429

430
  //---------------------------------------------------------------------
431
  // Implementation of HierarchicalBeanFactory interface
432
  //---------------------------------------------------------------------
433

434
  @Override
435
  @Nullable
436
  public BeanFactory getParentBeanFactory() {
437
    return getParent();
3✔
438
  }
439

440
  @Override
441
  public boolean containsLocalBean(String name) {
442
    return getBeanFactory().containsLocalBean(name);
5✔
443
  }
444

445
  /**
446
   * Return the internal bean factory of the parent context if it implements
447
   * ConfigurableApplicationContext; else, return the parent context itself.
448
   *
449
   * @see ConfigurableApplicationContext#unwrapFactory
450
   */
451
  @Nullable
452
  protected BeanFactory getInternalParentBeanFactory() {
453
    ApplicationContext parent = getParent();
3✔
454
    return parent instanceof ConfigurableApplicationContext cac ? cac.getBeanFactory() : parent;
11✔
455
  }
456

457
  //---------------------------------------------------------------------
458
  // Implementation of MessageSource interface
459
  //---------------------------------------------------------------------
460

461
  @Nullable
462
  @Override
463
  public String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale) {
464
    return getMessageSource().getMessage(code, args, defaultMessage, locale);
8✔
465
  }
466

467
  @Override
468
  public String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException {
469
    return getMessageSource().getMessage(code, args, locale);
7✔
470
  }
471

472
  @Override
473
  public String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException {
474
    return getMessageSource().getMessage(resolvable, locale);
6✔
475
  }
476

477
  /**
478
   * Return the internal MessageSource used by the context.
479
   *
480
   * @return the internal MessageSource (never {@code null})
481
   * @throws IllegalStateException if the context has not been initialized yet
482
   */
483
  private MessageSource getMessageSource() throws IllegalStateException {
484
    if (this.messageSource == null) {
3✔
485
      throw new IllegalStateException("MessageSource not initialized - call 'refresh' before accessing messages via the context: " + this);
7✔
486
    }
487
    return this.messageSource;
3✔
488
  }
489

490
  /**
491
   * Return the internal message source of the parent context if it is an
492
   * AbstractApplicationContext too; else, return the parent context itself.
493
   */
494
  @Nullable
495
  protected MessageSource getInternalParentMessageSource() {
496
    ApplicationContext parent = getParent();
3✔
497
    return parent instanceof AbstractApplicationContext abc ? abc.messageSource : parent;
11✔
498
  }
499

500
  /**
501
   * Reset reflection metadata caches, in particular the
502
   * {@link ReflectionUtils}, {@link AnnotationUtils}, {@link ResolvableType}
503
   *
504
   * @see ReflectionUtils#clearCache()
505
   * @see AnnotationUtils#clearCache()
506
   * @see ResolvableType#clearCache()
507
   * @since 4.0
508
   */
509
  protected void resetCommonCaches() {
510
    ReflectionUtils.clearCache();
1✔
511
    AnnotationUtils.clearCache();
1✔
512
    ResolvableType.clearCache();
1✔
513
    CachedIntrospectionResults.clearClassLoader(getClassLoader());
3✔
514
    if (bootstrapContext != null) {
3✔
515
      bootstrapContext.clearCache();
3✔
516
    }
517
  }
1✔
518

519
  //---------------------------------------------------------------------
520
  // Implementation of ApplicationContext interface
521
  //---------------------------------------------------------------------
522

523
  @Override
524
  public void refresh() throws BeansException, IllegalStateException {
525
    this.startupShutdownLock.lock();
3✔
526
    try {
527
      this.startupShutdownThread = Thread.currentThread();
3✔
528

529
      // Prepare this context for refreshing.
530
      prepareRefresh();
2✔
531

532
      // Tell the subclass to refresh the internal bean factory.
533
      ConfigurableBeanFactory beanFactory = obtainFreshBeanFactory();
3✔
534

535
      // register framework beans
536
      registerFrameworkComponents(beanFactory);
3✔
537

538
      // Prepare BeanFactory
539
      prepareBeanFactory(beanFactory);
3✔
540

541
      try {
542
        // Allows post-processing of the bean factory in context subclasses.
543
        postProcessBeanFactory(beanFactory);
3✔
544

545
        // Invoke factory processors registered as beans in the context.
546
        invokeBeanFactoryPostProcessors(beanFactory);
3✔
547

548
        // Register bean processors that intercept bean creation.
549
        registerBeanPostProcessors(beanFactory);
3✔
550

551
        // Initialize message source for this context.
552
        initMessageSource();
2✔
553

554
        // Initialize event multicaster for this context.
555
        initApplicationEventMulticaster();
2✔
556

557
        // Initialization singletons that has already in context
558
        // Initialize other special beans in specific context subclasses.
559
        // for example a Web Server
560
        onRefresh();
2✔
561

562
        // Check for listener beans and register them.
563
        registerApplicationListeners();
2✔
564

565
        // Instantiate all remaining (non-lazy-init) singletons.
566
        finishBeanFactoryInitialization(beanFactory);
3✔
567

568
        // Finish refresh
569
        finishRefresh();
2✔
570
      }
571

572
      catch (RuntimeException | Error ex) {
1✔
573
        applyState(State.FAILED);
3✔
574

575
        logger.warn("Exception encountered during context initialization - cancelling refresh attempt: {}",
5✔
576
                ex.toString());
1✔
577

578
        // Destroy already created singletons to avoid dangling resources.
579
        destroyBeans();
2✔
580

581
        // Reset 'active' flag.
582
        cancelRefresh(ex);
3✔
583

584
        // Propagate exception to caller.
585
        throw ex;
2✔
586
      }
1✔
587
    }
588
    finally {
589
      this.startupShutdownThread = null;
3✔
590
      this.startupShutdownLock.unlock();
3✔
591
    }
592
  }
1✔
593

594
  /**
595
   * Prepare to load context
596
   */
597
  protected void prepareRefresh() {
598
    this.startupDate = Instant.now();
3✔
599
    this.closed.set(false);
4✔
600
    this.active.set(true);
4✔
601
    applyState(State.STARTING);
3✔
602
    ApplicationContextHolder.register(this); // @since 4.0
3✔
603

604
    logger.info("Starting application context at '{}'", startupDate);
6✔
605

606
    ConfigurableEnvironment environment = getEnvironment();
3✔
607

608
    // Initialize any placeholder property sources in the context environment.
609
    initPropertySources();
2✔
610

611
    environment.validateRequiredProperties();
2✔
612

613
    // Store pre-refresh ApplicationListeners...
614
    if (this.earlyApplicationListeners == null) {
3✔
615
      this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
8✔
616
    }
617
    else {
618
      // Reset local application listeners to pre-refresh state.
619
      this.applicationListeners.clear();
3✔
620
      this.applicationListeners.addAll(this.earlyApplicationListeners);
6✔
621
    }
622

623
    // Allow for the collection of early ApplicationEvents,
624
    // to be published once the multicaster is available...
625
    this.earlyApplicationEvents = new LinkedHashSet<>();
5✔
626

627
    if (logger.isDebugEnabled()) {
4✔
628
      if (logger.isTraceEnabled()) {
4!
629
        logger.trace("Refreshing {}", this);
×
630
      }
631
      else {
632
        logger.debug("Refreshing {}", getDisplayName());
6✔
633
      }
634
    }
635
  }
1✔
636

637
  /**
638
   * <p>
639
   * load properties files or itself strategies
640
   */
641
  protected void initPropertySources() throws ApplicationContextException {
642
    // for subclasses loading properties or prepare property-source
643
  }
1✔
644

645
  /**
646
   * Register Framework Beans
647
   */
648
  protected void registerFrameworkComponents(ConfigurableBeanFactory beanFactory) {
649
    logger.debug("Registering framework components");
4✔
650

651
    BootstrapContext bootstrapContext = getBootstrapContext();
3✔
652
    beanFactory.registerSingleton(getDependencyInjector(bootstrapContext));
5✔
653

654
    if (!beanFactory.containsLocalBean(BootstrapContext.BEAN_NAME)) {
4!
655
      beanFactory.registerSingleton(BootstrapContext.BEAN_NAME, bootstrapContext);
4✔
656
    }
657
    // Register default environment beans.
658
    if (!beanFactory.containsLocalBean(Environment.ENVIRONMENT_BEAN_NAME)) {
4!
659
      beanFactory.registerSingleton(Environment.ENVIRONMENT_BEAN_NAME, getEnvironment());
5✔
660
    }
661
    if (!beanFactory.containsLocalBean(Environment.SYSTEM_PROPERTIES_BEAN_NAME)) {
4!
662
      beanFactory.registerSingleton(Environment.SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
6✔
663
    }
664
    if (!beanFactory.containsLocalBean(Environment.SYSTEM_ENVIRONMENT_BEAN_NAME)) {
4!
665
      beanFactory.registerSingleton(Environment.SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
6✔
666
    }
667
  }
1✔
668

669
  private DependencyInjector getDependencyInjector(BootstrapContext bootstrapContext) {
670
    DependencyInjector injector = getInjector();
3✔
671
    var strategies = TodayStrategies.find(DependencyResolvingStrategy.class, getClassLoader(), bootstrapContext);
6✔
672
    injector.setResolvingStrategies(new DependencyResolvingStrategies(strategies));
6✔
673
    return injector;
2✔
674
  }
675

676
  /**
677
   * Initialization singletons that has already in context
678
   */
679
  protected void onRefresh() {
680
    // sub-classes Initialization
681
  }
1✔
682

683
  /**
684
   * Tell the subclass to refresh the internal bean factory.
685
   *
686
   * @return the fresh BeanFactory instance
687
   * @see #refreshBeanFactory()
688
   * @see #getBeanFactory()
689
   * @since 4.0
690
   */
691
  protected ConfigurableBeanFactory obtainFreshBeanFactory() {
692
    refreshBeanFactory();
2✔
693
    return getBeanFactory();
3✔
694
  }
695

696
  /**
697
   * Configure the factory's standard context characteristics,
698
   * such as the context's ClassLoader and post-processors.
699
   *
700
   * @param beanFactory the BeanFactory to configure
701
   */
702
  protected void prepareBeanFactory(ConfigurableBeanFactory beanFactory) {
703
    logger.debug("Preparing bean-factory: {}", beanFactory);
5✔
704
    // Tell the internal bean factory to use the context's class loader etc.
705
    ClassLoader classLoader = getClassLoader();
3✔
706
    beanFactory.setBeanClassLoader(classLoader);
3✔
707
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
7✔
708
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
8✔
709

710
    // Configure the bean factory with context callbacks.
711
    beanFactory.addBeanPostProcessor(new ContextAwareProcessor(this, getBootstrapContext()));
8✔
712
    // Register early post-processor for detecting inner beans as ApplicationListeners.
713
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
6✔
714

715
    // Detect a LoadTimeWeaver and prepare for weaving, if found.
716
    if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
6!
717
      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
×
718
      // Set a temporary ClassLoader for type matching.
719
      beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
×
720
    }
721

722
    // @since 4.0
723
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
3✔
724
    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
3✔
725
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
3✔
726
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
3✔
727
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
3✔
728
    beanFactory.ignoreDependencyInterface(BootstrapContextAware.class);
3✔
729
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
3✔
730

731
    // BeanFactory interface not registered as resolvable type in a plain factory.
732
    // MessageSource registered (and found for autowiring) as a bean.
733
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
4✔
734
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
4✔
735
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
4✔
736
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);
4✔
737

738
    // loading some outside beans
739

740
    BootstrapContext bootstrapContext = getBootstrapContext();
3✔
741
    var strategies = TodayStrategies.find(BeanDefinitionLoader.class, classLoader, bootstrapContext);
5✔
742
    if (!strategies.isEmpty()) {
3!
743
      for (BeanDefinitionLoader loader : strategies) {
×
744
        loader.loadBeanDefinitions(bootstrapContext);
×
745
      }
×
746
    }
747
  }
1✔
748

749
  // post-processor
750

751
  /**
752
   * Modify the application context's internal bean factory after its standard
753
   * initialization. The initial definition resources will have been loaded but no
754
   * post-processors will have run and no derived bean definitions will have been
755
   * registered, and most importantly, no beans will have been instantiated yet.
756
   * <p>This template method allows for registering special BeanPostProcessors
757
   * etc in certain AbstractApplicationContext subclasses.
758
   *
759
   * @param beanFactory the bean factory used by the application context
760
   */
761
  protected void postProcessBeanFactory(ConfigurableBeanFactory beanFactory) { }
1✔
762

763
  /**
764
   * Instantiate and invoke all registered BeanFactoryPostProcessor beans,
765
   * respecting explicit order if given.
766
   * <p>Must be called before singleton instantiation.
767
   */
768
  protected void invokeBeanFactoryPostProcessors(ConfigurableBeanFactory beanFactory) {
769
    logger.debug("Invoking bean-factory-post-processors");
4✔
770
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, factoryPostProcessors);
4✔
771

772
    // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
773
    // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
774
    if (!NativeDetector.inNativeImage()
3✔
775
            && beanFactory.getTempClassLoader() == null
4!
776
            && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
2✔
777
      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
6✔
778
      beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
7✔
779
    }
780
  }
1✔
781

782
  /**
783
   * Instantiate and register all BeanPostProcessor beans,
784
   * respecting explicit order if given.
785
   * <p>Must be called before any instantiation of application beans.
786
   */
787
  protected void registerBeanPostProcessors(ConfigurableBeanFactory beanFactory) {
788
    logger.debug("Registering bean-post-processors");
4✔
789
    PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
3✔
790
  }
1✔
791

792
  /**
793
   * Initialize the MessageSource.
794
   * Use parent's if none defined in this context.
795
   */
796
  protected void initMessageSource() {
797
    ConfigurableBeanFactory beanFactory = getBeanFactory();
3✔
798
    if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
4✔
799
      this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
7✔
800
      // Make MessageSource aware of parent MessageSource.
801
      if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource hms) {
12!
802
        if (hms.getParentMessageSource() == null) {
3!
803
          // Only set parent context as parent MessageSource if no parent MessageSource
804
          // registered already.
805
          hms.setParentMessageSource(getInternalParentMessageSource());
4✔
806
        }
807
      }
808
      if (logger.isTraceEnabled()) {
4!
809
        logger.trace("Using MessageSource [{}]", messageSource);
×
810
      }
811
    }
812
    else {
813
      // Use empty MessageSource to be able to accept getMessage calls.
814
      DelegatingMessageSource dms = new DelegatingMessageSource();
4✔
815
      dms.setParentMessageSource(getInternalParentMessageSource());
4✔
816
      this.messageSource = dms;
3✔
817
      beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, messageSource);
5✔
818
      if (logger.isTraceEnabled()) {
4!
819
        logger.trace("No '{}' bean, using [{}]", MESSAGE_SOURCE_BEAN_NAME, messageSource);
×
820
      }
821
    }
822
  }
1✔
823

824
  /**
825
   * Cancel this context's refresh attempt, after an exception got thrown.
826
   *
827
   * @param ex the exception that led to the cancellation
828
   */
829
  protected void cancelRefresh(Throwable ex) {
830
    this.active.set(false);
4✔
831

832
    // Reset common introspection caches in core infrastructure.
833
    resetCommonCaches();
2✔
834
  }
1✔
835

836
  /**
837
   * Actually performs context closing: publishes a ContextClosedEvent and
838
   * destroys the singletons in the bean factory of this application context.
839
   * <p>Called by both {@code close()} and a JVM shutdown hook, if any.
840
   *
841
   * @see ContextClosedEvent
842
   * @see #destroyBeans()
843
   * @see #close()
844
   * @since 4.0
845
   */
846
  protected void doClose() {
847
    // Check whether an actual close attempt is necessary...
848
    if (active.get() && closed.compareAndSet(false, true)) {
10!
849
      logger.info("Closing: [{}] at [{}]", this, Instant.now());
6✔
850

851
      try {
852
        // Publish shutdown event.
853
        publishEvent(new ContextClosedEvent(this));
6✔
854
      }
855
      catch (Throwable ex) {
×
856
        logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
×
857
      }
1✔
858

859
      // Stop all Lifecycle beans, to avoid delays during individual destruction.
860
      if (lifecycleProcessor != null) {
3✔
861
        try {
862
          lifecycleProcessor.onClose();
3✔
863
        }
864
        catch (Throwable ex) {
×
865
          logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
×
866
        }
1✔
867
      }
868
      // Destroy all cached singletons in the context's BeanFactory.
869
      destroyBeans();
2✔
870

871
      // Close the state of this context itself.
872
      closeBeanFactory();
2✔
873

874
      // Let subclasses do some final clean-up if they wish...
875
      onClose();
2✔
876

877
      // Reset common introspection caches to avoid class reference leaks.
878
      resetCommonCaches();
2✔
879

880
      // Reset local application listeners to pre-refresh state.
881
      if (earlyApplicationListeners != null) {
3!
882
        applicationListeners.clear();
3✔
883
        applicationListeners.addAll(earlyApplicationListeners);
6✔
884
      }
885

886
      // Reset internal delegates.
887
      this.applicationEventMulticaster = null;
3✔
888
      this.messageSource = null;
3✔
889
      this.lifecycleProcessor = null;
3✔
890

891
      // Switch to inactive.
892
      active.set(false);
4✔
893
    }
894
  }
1✔
895

896
  /**
897
   * Register a shutdown hook {@linkplain Thread#getName() named}
898
   * {@code ContextShutdownHook} with the JVM runtime, closing this
899
   * context on JVM shutdown unless it has already been closed at that time.
900
   * <p>Delegates to {@code doClose()} for the actual closing procedure.
901
   *
902
   * @see Runtime#addShutdownHook
903
   * @see ConfigurableApplicationContext#SHUTDOWN_HOOK_THREAD_NAME
904
   * @see #close()
905
   * @see #doClose()
906
   */
907
  @Override
908
  public void registerShutdownHook() {
909
    if (shutdownHook == null) {
3!
910
      // No shutdown hook registered yet.
911
      this.shutdownHook = new Thread(SHUTDOWN_HOOK_THREAD_NAME) {
14✔
912
        @Override
913
        public void run() {
914
          if (isStartupShutdownThreadStuck()) {
4!
915
            active.set(false);
×
916
            return;
×
917
          }
918
          startupShutdownLock.lock();
4✔
919
          try {
920
            doClose();
3✔
921
          }
922
          finally {
923
            startupShutdownLock.unlock();
4✔
924
          }
925
        }
1✔
926
      };
927
      Runtime.getRuntime().addShutdownHook(shutdownHook);
4✔
928
    }
929
  }
1✔
930

931
  /**
932
   * Determine whether an active startup/shutdown thread is currently stuck,
933
   * e.g. through a {@code System.exit} call in a user component.
934
   */
935
  private boolean isStartupShutdownThreadStuck() {
936
    Thread activeThread = this.startupShutdownThread;
3✔
937
    if (activeThread != null && activeThread.getState() == Thread.State.WAITING) {
6!
938
      // Indefinitely waiting: might be Thread.join or the like, or System.exit
939
      activeThread.interrupt();
×
940
      try {
941
        // Leave just a little bit of time for the interruption to show effect
942
        Thread.sleep(1);
×
943
      }
944
      catch (InterruptedException ex) {
×
945
        Thread.currentThread().interrupt();
×
946
      }
×
947

948
      // Interrupted but still waiting: very likely a System.exit call
949
      return activeThread.getState() == Thread.State.WAITING;
×
950
    }
951
    return false;
2✔
952
  }
953

954
  /**
955
   * Close this application context, destroying all beans in its bean factory.
956
   * <p>Delegates to {@code doClose()} for the actual closing procedure.
957
   * Also removes a JVM shutdown hook, if registered, as it's not needed anymore.
958
   *
959
   * @see #doClose()
960
   * @see #registerShutdownHook()
961
   */
962
  @Override
963
  public void close() {
964
    if (isStartupShutdownThreadStuck()) {
3!
965
      active.set(false);
×
966
      return;
×
967
    }
968
    startupShutdownLock.lock();
3✔
969
    applyState(State.CLOSING);
3✔
970
    try {
971
      startupShutdownThread = Thread.currentThread();
3✔
972
      doClose();
2✔
973
      // If we registered a JVM shutdown hook, we don't need it anymore now:
974
      // We've already explicitly closed the context.
975
      if (shutdownHook != null) {
3✔
976
        try {
977
          Runtime.getRuntime().removeShutdownHook(shutdownHook);
5✔
978
        }
979
        catch (IllegalStateException ex) {
×
980
          // ignore - VM is already shutting down
981
        }
1✔
982
      }
983
    }
984
    finally {
985
      applyState(State.CLOSED);
3✔
986
      ApplicationContextHolder.remove(this);
2✔
987
      startupShutdownThread = null;
3✔
988
      startupShutdownLock.unlock();
3✔
989
    }
990
  }
1✔
991

992
  /**
993
   * Template method for destroying all beans that this context manages.
994
   * The default implementation destroy all cached singletons in this context,
995
   * invoking {@code DisposableBean.destroy()} and/or the specified
996
   * "destroy-method".
997
   * <p>Can be overridden to add context-specific bean destruction steps
998
   * right before or right after standard singleton destruction,
999
   * while the context's BeanFactory is still active.
1000
   *
1001
   * @see #getBeanFactory()
1002
   * @see ConfigurableBeanFactory#destroySingletons()
1003
   * @since 4.0
1004
   */
1005
  protected void destroyBeans() {
1006
    getBeanFactory().destroySingletons();
3✔
1007
  }
1✔
1008

1009
  /**
1010
   * Template method which can be overridden to add context-specific shutdown work.
1011
   * The default implementation is empty.
1012
   * <p>Called at the end of {@link #doClose}'s shutdown procedure, after
1013
   * this context's BeanFactory has been closed. If custom shutdown logic
1014
   * needs to execute while the BeanFactory is still active, override
1015
   * the {@link #destroyBeans()} method instead.
1016
   *
1017
   * @since 4.0
1018
   */
1019
  protected void onClose() {
1020
    // For subclasses: do nothing by default.
1021
  }
1✔
1022

1023
  @Override
1024
  public boolean isClosed() {
1025
    return this.closed.get();
4✔
1026
  }
1027

1028
  @Override
1029
  public boolean isActive() {
1030
    return active.get();
4✔
1031
  }
1032

1033
  @Override
1034
  @SuppressWarnings("unchecked")
1035
  public <T> T unwrapFactory(Class<T> requiredType) {
1036
    ConfigurableBeanFactory beanFactory = getBeanFactory();
3✔
1037
    if (requiredType.isInstance(beanFactory)) {
4!
1038
      return (T) beanFactory;
2✔
1039
    }
1040
    throw new IllegalArgumentException("bean factory must be a " + requiredType);
×
1041
  }
1042

1043
  @Override
1044
  public State getState() {
1045
    return state;
3✔
1046
  }
1047

1048
  protected void applyState(State state) {
1049
    this.state = state;
3✔
1050
  }
1✔
1051

1052
  @Override
1053
  public Instant getStartupDate() {
1054
    return startupDate;
3✔
1055
  }
1056

1057
  //---------------------------------------------------------------------
1058
  // Implementation of ConfigurableApplicationContext interface
1059
  //---------------------------------------------------------------------
1060

1061
  /**
1062
   * Set the parent of this application context.
1063
   * <p>The parent {@linkplain ApplicationContext#getEnvironment() environment} is
1064
   * {@linkplain ConfigurableEnvironment#merge(ConfigurableEnvironment) merged} with
1065
   * this (child) application context environment if the parent is non-{@code null} and
1066
   * its environment is an instance of {@link ConfigurableEnvironment}.
1067
   *
1068
   * @see ConfigurableEnvironment#merge(ConfigurableEnvironment)
1069
   */
1070
  @Override
1071
  public void setParent(@Nullable ApplicationContext parent) {
1072
    this.parent = parent;
3✔
1073
    if (parent != null) {
2✔
1074
      Environment parentEnvironment = parent.getEnvironment();
3✔
1075
      if (parentEnvironment instanceof ConfigurableEnvironment) {
3!
1076
        getEnvironment().merge((ConfigurableEnvironment) parentEnvironment);
5✔
1077
      }
1078
    }
1079
  }
1✔
1080

1081
  @Override
1082
  public ConfigurableEnvironment getEnvironment() {
1083
    ConfigurableEnvironment environment = this.environment;
3✔
1084
    if (environment == null) {
2✔
1085
      environment = createEnvironment();
3✔
1086
      this.environment = environment;
3✔
1087
    }
1088
    return environment;
2✔
1089
  }
1090

1091
  /**
1092
   * Create and return a new {@link StandardEnvironment}.
1093
   * <p>Subclasses may override this method in order to supply
1094
   * a custom {@link ConfigurableEnvironment} implementation.
1095
   */
1096
  protected ConfigurableEnvironment createEnvironment() {
1097
    return new StandardEnvironment();
4✔
1098
  }
1099

1100
  @Override
1101
  public void setEnvironment(@Nullable ConfigurableEnvironment environment) {
1102
    this.environment = environment;
3✔
1103
  }
1✔
1104

1105
  @Override
1106
  public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor) {
1107
    Assert.notNull(postProcessor, "BeanFactoryPostProcessor is required");
3✔
1108

1109
    factoryPostProcessors.add(postProcessor);
5✔
1110
  }
1✔
1111

1112
  //---------------------------------------------------------------------
1113
  // Implementation of BeanFactory interface
1114
  //---------------------------------------------------------------------
1115

1116
  /**
1117
   * Assert that this context's BeanFactory is currently active,
1118
   * throwing an {@link IllegalStateException} if it isn't.
1119
   * <p>Invoked by all {@link BeanFactory} delegation methods that depend
1120
   * on an active context, i.e. in particular all bean accessor methods.
1121
   */
1122
  protected void assertBeanFactoryActive() {
1123
    if (!active.get()) {
4✔
1124
      if (closed.get()) {
4✔
1125
        throw new IllegalStateException(getDisplayName() + " has been closed already");
7✔
1126
      }
1127
      else {
1128
        throw new IllegalStateException(getDisplayName() + " has not been refreshed yet");
7✔
1129
      }
1130
    }
1131
  }
1✔
1132

1133
  @Nullable
1134
  @Override
1135
  public Object getBean(String name) {
1136
    assertBeanFactoryActive();
2✔
1137
    return getBeanFactory().getBean(name);
5✔
1138
  }
1139

1140
  @Nullable
1141
  @Override
1142
  public Object getBean(String name, Object... args) throws BeansException {
1143
    assertBeanFactoryActive();
×
1144
    return getBeanFactory().getBean(name, args);
×
1145
  }
1146

1147
  @Override
1148
  public <T> T getBean(Class<T> requiredType) {
1149
    assertBeanFactoryActive();
2✔
1150
    return getBeanFactory().getBean(requiredType);
5✔
1151
  }
1152

1153
  @Override
1154
  public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
1155
    assertBeanFactoryActive();
2✔
1156
    return getBeanFactory().getBean(requiredType, args);
6✔
1157
  }
1158

1159
  @Override
1160
  public <T> T getBean(String name, Class<T> requiredType) {
1161
    assertBeanFactoryActive();
2✔
1162
    return getBeanFactory().getBean(name, requiredType);
6✔
1163
  }
1164

1165
  @Nullable
1166
  @Override
1167
  public <A extends Annotation> A findSynthesizedAnnotation(String beanName, Class<A> annotationType) {
1168
    assertBeanFactoryActive();
×
1169
    return getBeanFactory().findSynthesizedAnnotation(beanName, annotationType);
×
1170
  }
1171

1172
  @Override
1173
  public <A extends Annotation> MergedAnnotation<A> findAnnotationOnBean(
1174
          String beanName, Class<A> annotationType) throws NoSuchBeanDefinitionException {
1175
    assertBeanFactoryActive();
×
1176
    return getBeanFactory().findAnnotationOnBean(beanName, annotationType);
×
1177
  }
1178

1179
  @Override
1180
  public <A extends Annotation> MergedAnnotation<A> findAnnotationOnBean(
1181
          String beanName, Class<A> annotationType, boolean allowFactoryBeanInit)
1182
          throws NoSuchBeanDefinitionException {
1183
    assertBeanFactoryActive();
×
1184
    return getBeanFactory().findAnnotationOnBean(beanName, annotationType, allowFactoryBeanInit);
×
1185
  }
1186

1187
  @Override
1188
  public <A extends Annotation> Set<A> findAllAnnotationsOnBean(
1189
          String beanName, Class<A> annotationType, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException {
1190
    assertBeanFactoryActive();
×
1191
    return getBeanFactory().findAllAnnotationsOnBean(beanName, annotationType, allowFactoryBeanInit);
×
1192
  }
1193

1194
  @Override
1195
  public <T> List<T> getAnnotatedBeans(Class<? extends Annotation> annotationType) {
1196
    assertBeanFactoryActive();
×
1197
    return getBeanFactory().getAnnotatedBeans(annotationType);
×
1198
  }
1199

1200
  @Override
1201
  public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) {
1202
    assertBeanFactoryActive();
2✔
1203
    return getBeanFactory().getBeansWithAnnotation(annotationType);
5✔
1204
  }
1205

1206
  @Override
1207
  public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType, boolean includeNonSingletons) {
1208
    assertBeanFactoryActive();
×
1209
    return getBeanFactory().getBeansWithAnnotation(annotationType, includeNonSingletons);
×
1210
  }
1211

1212
  @Override
1213
  public boolean isSingleton(String name) {
1214
    assertBeanFactoryActive();
2✔
1215
    return getBeanFactory().isSingleton(name);
5✔
1216
  }
1217

1218
  @Override
1219
  public boolean isPrototype(String name) {
1220
    assertBeanFactoryActive();
2✔
1221
    return getBeanFactory().isPrototype(name);
5✔
1222
  }
1223

1224
  @Nullable
1225
  @Override
1226
  public Class<?> getType(String name) {
1227
    assertBeanFactoryActive();
2✔
1228
    return getBeanFactory().getType(name);
5✔
1229
  }
1230

1231
  @Nullable
1232
  @Override
1233
  public Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException {
1234
    assertBeanFactoryActive();
×
1235
    return getBeanFactory().getType(name, allowFactoryBeanInit);
×
1236
  }
1237

1238
  @Override
1239
  public Set<String> getBeanNamesForAnnotation(Class<? extends Annotation> annotationType) {
1240
    assertBeanFactoryActive();
2✔
1241
    return getBeanFactory().getBeanNamesForAnnotation(annotationType);
5✔
1242
  }
1243

1244
  @Override
1245
  public boolean containsBean(String name) {
1246
    return getBeanFactory().containsBean(name);
5✔
1247
  }
1248

1249
  @Override
1250
  public boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException {
1251
    assertBeanFactoryActive();
2✔
1252
    return getBeanFactory().isTypeMatch(name, typeToMatch);
6✔
1253
  }
1254

1255
  @Override
1256
  public boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException {
1257
    assertBeanFactoryActive();
×
1258
    return getBeanFactory().isTypeMatch(name, typeToMatch);
×
1259
  }
1260

1261
  @Override
1262
  public <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType) {
1263
    assertBeanFactoryActive();
2✔
1264
    return getBeanFactory().getBeanProvider(requiredType);
5✔
1265
  }
1266

1267
  @Override
1268
  public <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType) {
1269
    assertBeanFactoryActive();
2✔
1270
    return getBeanFactory().getBeanProvider(requiredType);
5✔
1271
  }
1272

1273
  @Override
1274
  public <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType, boolean allowEagerInit) {
1275
    assertBeanFactoryActive();
×
1276
    return getBeanFactory().getBeanProvider(requiredType, allowEagerInit);
×
1277
  }
1278

1279
  @Override
1280
  public <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType, boolean allowEagerInit) {
1281
    assertBeanFactoryActive();
×
1282
    return getBeanFactory().getBeanProvider(requiredType, allowEagerInit);
×
1283
  }
1284

1285
  @Override
1286
  public String[] getAliases(String name) {
1287
    assertBeanFactoryActive();
2✔
1288
    return getBeanFactory().getAliases(name);
5✔
1289
  }
1290

1291
  // type lookup
1292

1293
  @Override
1294
  public <T> List<T> getBeans(Class<T> requiredType) {
1295
    assertBeanFactoryActive();
×
1296
    return getBeanFactory().getBeans(requiredType);
×
1297
  }
1298

1299
  @Override
1300
  public Set<String> getBeanNamesForType(@Nullable Class<?> type) {
1301
    assertBeanFactoryActive();
2✔
1302
    return getBeanFactory().getBeanNamesForType(type);
5✔
1303
  }
1304

1305
  @Override
1306
  public Set<String> getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
1307
    assertBeanFactoryActive();
2✔
1308
    return getBeanFactory().getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
7✔
1309
  }
1310

1311
  @Override
1312
  public <T> Map<String, T> getBeansOfType(Class<T> type) {
1313
    assertBeanFactoryActive();
2✔
1314
    return getBeanFactory().getBeansOfType(type);
5✔
1315
  }
1316

1317
  @Override
1318
  public <T> Map<String, T> getBeansOfType(@Nullable Class<T> requiredType, boolean includeNonSingletons, boolean allowEagerInit) {
1319
    assertBeanFactoryActive();
2✔
1320
    return getBeanFactory().getBeansOfType(requiredType, includeNonSingletons, allowEagerInit);
7✔
1321
  }
1322

1323
  @Override
1324
  public <T> Map<String, T> getBeansOfType(ResolvableType requiredType, boolean includeNonSingletons, boolean allowEagerInit) {
1325
    assertBeanFactoryActive();
×
1326
    return getBeanFactory().getBeansOfType(requiredType, includeNonSingletons, allowEagerInit);
×
1327
  }
1328

1329
  @Override
1330
  public Set<String> getBeanNamesForType(ResolvableType requiredType) {
1331
    assertBeanFactoryActive();
×
1332
    return getBeanFactory().getBeanNamesForType(requiredType);
×
1333
  }
1334

1335
  @Override
1336
  public Set<String> getBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
1337
    assertBeanFactoryActive();
×
1338
    return getBeanFactory().getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
×
1339
  }
1340

1341
  @Override
1342
  public boolean containsBeanDefinition(String beanName) {
1343
    assertBeanFactoryActive();
×
1344
    return getBeanFactory().containsBeanDefinition(beanName);
×
1345
  }
1346

1347
  @Override
1348
  public BeanDefinition getBeanDefinition(String beanName) throws BeansException {
1349
    assertBeanFactoryActive();
×
1350
    return getBeanFactory().getBeanDefinition(beanName);
×
1351
  }
1352

1353
  @Override
1354
  public int getBeanDefinitionCount() {
1355
    assertBeanFactoryActive();
×
1356
    return getBeanFactory().getBeanDefinitionCount();
×
1357
  }
1358

1359
  @Override
1360
  public String[] getBeanDefinitionNames() {
1361
    assertBeanFactoryActive();
×
1362
    return new String[0];
×
1363
  }
1364

1365
  @Override
1366
  public DependencyInjector getInjector() {
1367
    return getBeanFactory().getInjector();
4✔
1368
  }
1369

1370
  //---------------------------------------------------------------------
1371
  // Implementation of Lifecycle interface
1372
  //---------------------------------------------------------------------
1373

1374
  @Override
1375
  public void start() {
1376
    getLifecycleProcessor().start();
3✔
1377
    publishEvent(new ContextStartedEvent(this));
6✔
1378
  }
1✔
1379

1380
  @Override
1381
  public void stop() {
1382
    getLifecycleProcessor().stop();
3✔
1383
    publishEvent(new ContextStoppedEvent(this));
6✔
1384
  }
1✔
1385

1386
  @Override
1387
  public void restart() {
1388
    getLifecycleProcessor().onRestart();
3✔
1389
    publishEvent(new ContextRestartedEvent(this));
6✔
1390
  }
1✔
1391

1392
  @Override
1393
  public boolean isRunning() {
1394
    return this.lifecycleProcessor != null && this.lifecycleProcessor.isRunning();
11!
1395
  }
1396

1397
  // lifecycleProcessor
1398

1399
  /**
1400
   * Initialize the LifecycleProcessor.
1401
   * Uses DefaultLifecycleProcessor if none defined in the context.
1402
   *
1403
   * @see DefaultLifecycleProcessor
1404
   */
1405
  protected void initLifecycleProcessor() {
1406
    if (lifecycleProcessor == null) {
3✔
1407
      ConfigurableBeanFactory beanFactory = getBeanFactory();
3✔
1408
      if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
4✔
1409
        this.lifecycleProcessor = beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
7✔
1410
        if (logger.isTraceEnabled()) {
4!
1411
          logger.trace("Using LifecycleProcessor [{}]", lifecycleProcessor);
×
1412
        }
1413
      }
1414
      else {
1415
        DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
4✔
1416
        defaultProcessor.setBeanFactory(beanFactory);
3✔
1417
        this.lifecycleProcessor = defaultProcessor;
3✔
1418
        beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
5✔
1419
        if (logger.isTraceEnabled()) {
4!
1420
          logger.trace("No '{}' bean, using [{}]", LIFECYCLE_PROCESSOR_BEAN_NAME, lifecycleProcessor.getClass().getSimpleName());
×
1421
        }
1422
      }
1423
    }
1424
  }
1✔
1425

1426
  /**
1427
   * Return the internal LifecycleProcessor used by the context.
1428
   *
1429
   * @return the internal LifecycleProcessor (never {@code null})
1430
   * @throws IllegalStateException if the context has not been initialized yet
1431
   */
1432
  public LifecycleProcessor getLifecycleProcessor() throws IllegalStateException {
1433
    if (this.lifecycleProcessor == null) {
3!
1434
      throw new IllegalStateException(
×
1435
              "LifecycleProcessor not initialized - call 'refresh' before invoking lifecycle methods via the context: " + this);
1436
    }
1437
    return this.lifecycleProcessor;
3✔
1438
  }
1439

1440
  //---------------------------------------------------------------------
1441
  // Implementation of ApplicationEventPublisher interface
1442
  //---------------------------------------------------------------------
1443

1444
  /**
1445
   * Return the internal ApplicationEventMulticaster used by the context.
1446
   *
1447
   * @return the internal ApplicationEventMulticaster (never {@code null})
1448
   * @throws IllegalStateException if the context has not been initialized yet
1449
   */
1450
  public ApplicationEventMulticaster getApplicationEventMulticaster() throws IllegalStateException {
1451
    if (this.applicationEventMulticaster == null) {
3!
1452
      throw new IllegalStateException(
×
1453
              "ApplicationEventMulticaster not initialized - call 'refresh' before multicasting events via the context: " + this);
1454
    }
1455
    return this.applicationEventMulticaster;
3✔
1456
  }
1457

1458
  /**
1459
   * Initialize the ApplicationEventMulticaster.
1460
   * Uses SimpleApplicationEventMulticaster if none defined in the context.
1461
   *
1462
   * @see SimpleApplicationEventMulticaster
1463
   */
1464
  protected void initApplicationEventMulticaster() {
1465
    ConfigurableBeanFactory beanFactory = getBeanFactory();
3✔
1466
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
4✔
1467
      this.applicationEventMulticaster =
4✔
1468
              beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
3✔
1469
      if (logger.isTraceEnabled()) {
4!
1470
        logger.trace("Using ApplicationEventMulticaster [{}]", applicationEventMulticaster);
×
1471
      }
1472
    }
1473
    else {
1474
      this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
6✔
1475
      beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, applicationEventMulticaster);
5✔
1476
      if (logger.isTraceEnabled()) {
4!
1477
        logger.trace("No '{}' bean, using [{}]",
×
1478
                APPLICATION_EVENT_MULTICASTER_BEAN_NAME, applicationEventMulticaster.getClass().getSimpleName());
×
1479
      }
1480
    }
1481
  }
1✔
1482

1483
  /**
1484
   * Return the list of statically specified ApplicationListeners.
1485
   */
1486
  public Collection<ApplicationListener<?>> getApplicationListeners() {
1487
    return this.applicationListeners;
3✔
1488
  }
1489

1490
  /**
1491
   * Publish the given event to all listeners.
1492
   * <p>Note: Listeners get initialized after the MessageSource, to be able
1493
   * to access it within listener implementations. Thus, MessageSource
1494
   * implementations cannot publish events.
1495
   *
1496
   * @param event the event to publish (may be application-specific or a
1497
   * standard framework event)
1498
   */
1499
  @Override
1500
  public void publishEvent(ApplicationEvent event) {
1501
    publishEvent(event, null);
4✔
1502
  }
1✔
1503

1504
  /**
1505
   * Publish the given event to all listeners.
1506
   * <p>Note: Listeners get initialized after the MessageSource, to be able
1507
   * to access it within listener implementations. Thus, MessageSource
1508
   * implementations cannot publish events.
1509
   *
1510
   * @param event the event to publish (may be an {@link ApplicationEvent}
1511
   * or a payload object to be turned into a {@link PayloadApplicationEvent})
1512
   */
1513
  @Override
1514
  public void publishEvent(Object event) {
1515
    publishEvent(event, null);
4✔
1516
  }
1✔
1517

1518
  /**
1519
   * Publish the given event to all listeners.
1520
   * <p>This is the internal delegate that all other {@code publishEvent}
1521
   * methods refer to. It is not meant to be called directly but rather serves
1522
   * as a propagation mechanism between application contexts in a hierarchy,
1523
   * potentially overridden in subclasses for a custom propagation arrangement.
1524
   *
1525
   * @param event the event to publish (may be an {@link ApplicationEvent}
1526
   * or a payload object to be turned into a {@link PayloadApplicationEvent})
1527
   * @param typeHint the resolved event type, if known.
1528
   * The implementation of this method also tolerates a payload type hint for
1529
   * a payload object to be turned into a {@link PayloadApplicationEvent}.
1530
   * However, the recommended way is to construct an actual event object via
1531
   * {@link PayloadApplicationEvent#PayloadApplicationEvent(Object, Object, ResolvableType)}
1532
   * instead for such scenarios.
1533
   * @see ApplicationEventMulticaster#multicastEvent(ApplicationEvent, ResolvableType)
1534
   * @since 4.0
1535
   */
1536
  protected void publishEvent(Object event, @Nullable ResolvableType typeHint) {
1537
    Assert.notNull(event, "Event is required");
3✔
1538
    ResolvableType eventType = null;
2✔
1539

1540
    // Decorate event as an ApplicationEvent if necessary
1541
    ApplicationEvent applicationEvent;
1542
    if (event instanceof ApplicationEvent applEvent) {
6✔
1543
      applicationEvent = applEvent;
2✔
1544
      eventType = typeHint;
3✔
1545
    }
1546
    else {
1547
      ResolvableType payloadType = null;
2✔
1548
      if (typeHint != null && ApplicationEvent.class.isAssignableFrom(typeHint.toClass())) {
7✔
1549
        eventType = typeHint;
3✔
1550
      }
1551
      else {
1552
        payloadType = typeHint;
2✔
1553
      }
1554
      applicationEvent = new PayloadApplicationEvent<>(this, event, payloadType);
7✔
1555
    }
1556

1557
    // Determine event type only once (for multicast and parent publish)
1558
    if (eventType == null) {
2✔
1559
      eventType = ResolvableType.forInstance(applicationEvent);
3✔
1560
      if (typeHint == null) {
2✔
1561
        typeHint = eventType;
2✔
1562
      }
1563
    }
1564

1565
    // Multicast right now if possible - or lazily once the multicaster is initialized
1566
    if (this.earlyApplicationEvents != null) {
3✔
1567
      this.earlyApplicationEvents.add(applicationEvent);
6✔
1568
    }
1569
    else if (this.applicationEventMulticaster != null) {
3✔
1570
      this.applicationEventMulticaster.multicastEvent(applicationEvent, eventType);
5✔
1571
    }
1572

1573
    // Publish event via parent context as well...
1574
    if (parent != null) {
3✔
1575
      if (parent instanceof AbstractApplicationContext parentCtx) {
9✔
1576
        parentCtx.publishEvent(event, typeHint);
5✔
1577
      }
1578
      else {
1579
        this.parent.publishEvent(event);
4✔
1580
      }
1581
    }
1582
  }
1✔
1583

1584
  protected void registerApplicationListeners() {
1585
    logger.debug("Registering application-listeners");
4✔
1586

1587
    // Register statically specified listeners first.
1588
    ApplicationEventMulticaster eventMulticaster = getApplicationEventMulticaster();
3✔
1589
    for (ApplicationListener<?> listener : getApplicationListeners()) {
11✔
1590
      eventMulticaster.addApplicationListener(listener);
3✔
1591
    }
1✔
1592

1593
    // Do not initialize FactoryBeans here: We need to leave all regular beans
1594
    // uninitialized to let post-processors apply to them!
1595
    Set<String> listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
6✔
1596
    for (String listenerBeanName : listenerBeanNames) {
10✔
1597
      eventMulticaster.addApplicationListenerBean(listenerBeanName);
3✔
1598
    }
1✔
1599

1600
    logger.debug("Publish early application events");
4✔
1601
    // Publish early application events now that we finally have a multicaster...
1602
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
3✔
1603
    this.earlyApplicationEvents = null;
3✔
1604
    if (CollectionUtils.isNotEmpty(earlyEventsToProcess)) {
3✔
1605
      for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
10✔
1606
        eventMulticaster.multicastEvent(earlyEvent);
3✔
1607
      }
1✔
1608
    }
1609
  }
1✔
1610

1611
  /**
1612
   * Add a new ApplicationListener that will be notified on context events
1613
   * such as context refresh and context shutdown.
1614
   * <p>Note that any ApplicationListener registered here will be applied
1615
   * on refresh if the context is not active yet, or on the fly with the
1616
   * current event multicaster in case of a context that is already active.
1617
   *
1618
   * @param listener the ApplicationListener to register
1619
   * @see ContextRefreshedEvent
1620
   * @see ContextClosedEvent
1621
   */
1622
  @Override
1623
  public void addApplicationListener(ApplicationListener<?> listener) {
1624
    Assert.notNull(listener, "ApplicationListener is required");
3✔
1625
    if (applicationEventMulticaster != null) {
3✔
1626
      applicationEventMulticaster.addApplicationListener(listener);
4✔
1627
    }
1628
    applicationListeners.add(listener);
5✔
1629
  }
1✔
1630

1631
  @Override
1632
  public void removeApplicationListener(ApplicationListener<?> listener) {
1633
    Assert.notNull(listener, "ApplicationListener is required");
3✔
1634
    if (applicationEventMulticaster != null) {
3✔
1635
      applicationEventMulticaster.removeApplicationListener(listener);
4✔
1636
    }
1637
    applicationListeners.remove(listener);
5✔
1638
  }
1✔
1639

1640
  /**
1641
   * Finish the initialization of this context's bean factory,
1642
   * initializing all remaining singleton beans.
1643
   */
1644
  protected void finishBeanFactoryInitialization(ConfigurableBeanFactory beanFactory) {
1645
    // Initialize bootstrap executor for this context.
1646
    if (beanFactory.containsBean(BOOTSTRAP_EXECUTOR_BEAN_NAME) &&
7✔
1647
            beanFactory.isTypeMatch(BOOTSTRAP_EXECUTOR_BEAN_NAME, Executor.class)) {
2!
1648
      beanFactory.setBootstrapExecutor(
5✔
1649
              beanFactory.getBean(BOOTSTRAP_EXECUTOR_BEAN_NAME, Executor.class));
2✔
1650
    }
1651

1652
    // Initialize conversion service for this context.
1653
    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME)
7✔
1654
            && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
2!
1655
      beanFactory.setConversionService(
5✔
1656
              beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
2✔
1657
    }
1658

1659
    // Register a default embedded value resolver if no BeanFactoryPostProcessor
1660
    // (such as a PropertySourcesPlaceholderConfigurer bean) registered any before:
1661
    // at this point, primarily for resolution in annotation attribute values.
1662
    if (!beanFactory.hasEmbeddedValueResolver()) {
3✔
1663
      beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolveRequiredPlaceholders(strVal));
9✔
1664
    }
1665

1666
    // Call BeanFactoryInitializer beans early to allow for initializing specific other beans early.
1667
    var initializerNames = beanFactory.getBeanNamesForType(BeanFactoryInitializer.class, false, false);
6✔
1668
    for (String initializerName : initializerNames) {
6!
1669
      beanFactory.getBean(initializerName, BeanFactoryInitializer.class).initialize(beanFactory);
×
1670
    }
×
1671

1672
    // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
1673
    var weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
6✔
1674
    for (String weaverAwareName : weaverAwareNames) {
6!
1675
      try {
1676
        beanFactory.getBean(weaverAwareName, LoadTimeWeaverAware.class);
×
1677
      }
1678
      catch (BeanNotOfRequiredTypeException ex) {
×
1679
        logger.debug("Failed to initialize LoadTimeWeaverAware bean '{}' due to unexpected type mismatch: {}",
×
1680
                weaverAwareName, ex.getMessage());
×
1681
      }
×
1682
    }
×
1683

1684
    // Stop using the temporary ClassLoader for type matching.
1685
    beanFactory.setTempClassLoader(null);
3✔
1686

1687
    // Allow for caching all bean definition metadata, not expecting further changes.
1688
    beanFactory.freezeConfiguration();
2✔
1689

1690
    // Instantiate all remaining (non-lazy-init) singletons.
1691
    beanFactory.preInstantiateSingletons();
2✔
1692
  }
1✔
1693

1694
  /**
1695
   * Finish the refresh of this context, invoking the LifecycleProcessor's
1696
   * onRefresh() method and publishing the {@link ContextRefreshedEvent}.
1697
   */
1698
  protected void finishRefresh() {
1699
    // Reset common introspection caches in core infrastructure.
1700
    resetCommonCaches();
2✔
1701

1702
    // Clear context-level resource caches (such as ASM metadata from scanning).
1703
    clearResourceCaches();
2✔
1704

1705
    // Initialize lifecycle processor for this context.
1706
    initLifecycleProcessor();
2✔
1707

1708
    // Propagate refresh to lifecycle processor first.
1709
    getLifecycleProcessor().onRefresh();
3✔
1710

1711
    // Publish the final event.
1712
    publishEvent(new ContextRefreshedEvent(this));
6✔
1713

1714
    applyState(State.STARTED);
3✔
1715
    Duration duration = Duration.between(getStartupDate(), Instant.now());
5✔
1716
    logger.info("Application context startup in {} ms", duration.toMillis());
7✔
1717
  }
1✔
1718

1719
  @Override
1720
  public void clearResourceCaches() {
1721
    super.clearResourceCaches();
2✔
1722
    if (patternResourceLoader instanceof PathMatchingPatternResourceLoader pmprl) {
9✔
1723
      pmprl.clearCache();
2✔
1724
    }
1725
  }
1✔
1726

1727
  //---------------------------------------------------------------------
1728
  // Abstract methods that must be implemented by subclasses
1729
  //---------------------------------------------------------------------
1730

1731
  /**
1732
   * Subclasses must implement this method to perform the actual configuration load.
1733
   * The method is invoked by {@link #refresh()} before any other initialization work.
1734
   * <p>A subclass will either create a new bean factory and hold a reference to it,
1735
   * or return a single BeanFactory instance that it holds. In the latter case, it will
1736
   * usually throw an IllegalStateException if refreshing the context more than once.
1737
   *
1738
   * @throws BeansException if initialization of the bean factory failed
1739
   * @throws IllegalStateException if already initialized and multiple refresh
1740
   * attempts are not supported
1741
   * @since 4.0
1742
   */
1743
  protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;
1744

1745
  /**
1746
   * Subclasses must implement this method to release their internal bean factory.
1747
   * This method gets invoked by {@link #close()} after all other shutdown work.
1748
   * <p>Should never throw an exception but rather log shutdown failures.
1749
   *
1750
   * @since 4.0
1751
   */
1752
  protected void closeBeanFactory() { }
×
1753

1754
  /**
1755
   * Subclasses must return their internal bean factory here. They should implement the
1756
   * lookup efficiently, so that it can be called repeatedly without a performance penalty.
1757
   * <p>Note: Subclasses should check whether the context is still active before
1758
   * returning the internal bean factory. The internal factory should generally be
1759
   * considered unavailable once the context has been closed.
1760
   *
1761
   * @return this application context's internal bean factory (never {@code null})
1762
   * @throws IllegalStateException if the context does not hold an internal bean factory yet
1763
   * (usually if {@link #refresh()} has never been called) or if the context has been
1764
   * closed already
1765
   * @see #refreshBeanFactory()
1766
   * @see #closeBeanFactory()
1767
   */
1768
  @Override
1769
  public abstract ConfigurableBeanFactory getBeanFactory();
1770

1771
  // Object
1772

1773
  /**
1774
   * Return information about this context.
1775
   */
1776
  @Override
1777
  public String toString() {
1778
    return "%s: state: [%s], on startup date: %s, parent: %s".formatted(
8✔
1779
            getDisplayName(), state, startupDate, parent != null ? parent.getDisplayName() : "none");
23✔
1780
  }
1781

1782
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc