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

TAKETODAY / today-infrastructure / 17175530323

23 Aug 2025 12:36PM UTC coverage: 81.854% (+0.009%) from 81.845%
17175530323

push

github

TAKETODAY
:art:

59686 of 77901 branches covered (76.62%)

Branch coverage included in aggregate %.

141140 of 167446 relevant lines covered (84.29%)

3.6 hits per line

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

82.35
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.ContextPausedEvent;
74
import infra.context.event.ContextRefreshedEvent;
75
import infra.context.event.ContextRestartedEvent;
76
import infra.context.event.ContextStartedEvent;
77
import infra.context.event.ContextStoppedEvent;
78
import infra.context.event.SimpleApplicationEventMulticaster;
79
import infra.context.expression.EmbeddedValueResolverAware;
80
import infra.context.expression.StandardBeanExpressionResolver;
81
import infra.context.weaving.LoadTimeWeaverAware;
82
import infra.context.weaving.LoadTimeWeaverAwareProcessor;
83
import infra.core.NativeDetector;
84
import infra.core.ResolvableType;
85
import infra.core.annotation.AnnotationUtils;
86
import infra.core.annotation.MergedAnnotation;
87
import infra.core.conversion.ConversionService;
88
import infra.core.env.ConfigurableEnvironment;
89
import infra.core.env.Environment;
90
import infra.core.env.StandardEnvironment;
91
import infra.core.io.DefaultResourceLoader;
92
import infra.core.io.PathMatchingPatternResourceLoader;
93
import infra.core.io.PatternResourceLoader;
94
import infra.core.io.Resource;
95
import infra.core.io.ResourceConsumer;
96
import infra.core.io.ResourceLoader;
97
import infra.core.io.SmartResourceConsumer;
98
import infra.lang.Assert;
99
import infra.lang.Nullable;
100
import infra.lang.TodayStrategies;
101
import infra.logging.Logger;
102
import infra.logging.LoggerFactory;
103
import infra.util.CollectionUtils;
104
import infra.util.ObjectUtils;
105
import infra.util.ReflectionUtils;
106

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

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

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

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

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

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

193
  @Nullable
194
  private ConfigurableEnvironment environment;
195

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

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

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

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

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

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

214
  /** @since 4.0 */
215

216
  @Nullable
217
  private ExpressionEvaluator expressionEvaluator;
218

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

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

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

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

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

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

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

246
  @Nullable
247
  private BootstrapContext bootstrapContext;
248

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

607
    ConfigurableEnvironment environment = getEnvironment();
3✔
608

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

612
    environment.validateRequiredProperties();
2✔
613

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

739
    // loading some outside beans
740

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

750
  // post-processor
751

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1292
  // type lookup
1293

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

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

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

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

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

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

1330
  @Override
1331
  public String[] getBeanNamesForType(ResolvableType requiredType) {
1332
    assertBeanFactoryActive();
×
1333
    return getBeanFactory().getBeanNamesForType(requiredType);
×
1334
  }
1335

1336
  @Override
1337
  public String[] getBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
1338
    assertBeanFactoryActive();
×
1339
    return getBeanFactory().getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
×
1340
  }
1341

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

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

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

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

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

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

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

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

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

1393
  @Override
1394
  public void pause() {
1395
    getLifecycleProcessor().onPause();
3✔
1396
    publishEvent(new ContextPausedEvent(this));
6✔
1397
  }
1✔
1398

1399
  @Override
1400
  public boolean isRunning() {
1401
    return this.lifecycleProcessor != null && this.lifecycleProcessor.isRunning();
11!
1402
  }
1403

1404
  // lifecycleProcessor
1405

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

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

1447
  //---------------------------------------------------------------------
1448
  // Implementation of ApplicationEventPublisher interface
1449
  //---------------------------------------------------------------------
1450

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

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

1490
  /**
1491
   * Return the list of statically specified ApplicationListeners.
1492
   */
1493
  public Collection<ApplicationListener<?>> getApplicationListeners() {
1494
    return this.applicationListeners;
3✔
1495
  }
1496

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

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

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

1547
    // Decorate event as an ApplicationEvent if necessary
1548
    ApplicationEvent applicationEvent;
1549
    if (event instanceof ApplicationEvent applEvent) {
6✔
1550
      applicationEvent = applEvent;
2✔
1551
      eventType = typeHint;
3✔
1552
    }
1553
    else {
1554
      ResolvableType payloadType = null;
2✔
1555
      if (typeHint != null && ApplicationEvent.class.isAssignableFrom(typeHint.toClass())) {
7✔
1556
        eventType = typeHint;
3✔
1557
      }
1558
      else {
1559
        payloadType = typeHint;
2✔
1560
      }
1561
      applicationEvent = new PayloadApplicationEvent<>(this, event, payloadType);
7✔
1562
    }
1563

1564
    // Determine event type only once (for multicast and parent publish)
1565
    if (eventType == null) {
2✔
1566
      eventType = ResolvableType.forInstance(applicationEvent);
3✔
1567
      if (typeHint == null) {
2✔
1568
        typeHint = eventType;
2✔
1569
      }
1570
    }
1571

1572
    // Multicast right now if possible - or lazily once the multicaster is initialized
1573
    if (this.earlyApplicationEvents != null) {
3✔
1574
      this.earlyApplicationEvents.add(applicationEvent);
6✔
1575
    }
1576
    else if (this.applicationEventMulticaster != null) {
3✔
1577
      this.applicationEventMulticaster.multicastEvent(applicationEvent, eventType);
5✔
1578
    }
1579

1580
    // Publish event via parent context as well...
1581
    if (parent != null) {
3✔
1582
      if (parent instanceof AbstractApplicationContext parentCtx) {
9✔
1583
        parentCtx.publishEvent(event, typeHint);
5✔
1584
      }
1585
      else {
1586
        this.parent.publishEvent(event);
4✔
1587
      }
1588
    }
1589
  }
1✔
1590

1591
  protected void registerApplicationListeners() {
1592
    logger.debug("Registering application-listeners");
4✔
1593

1594
    // Register statically specified listeners first.
1595
    ApplicationEventMulticaster eventMulticaster = getApplicationEventMulticaster();
3✔
1596
    for (ApplicationListener<?> listener : getApplicationListeners()) {
11✔
1597
      eventMulticaster.addApplicationListener(listener);
3✔
1598
    }
1✔
1599

1600
    // Do not initialize FactoryBeans here: We need to leave all regular beans
1601
    // uninitialized to let post-processors apply to them!
1602
    var listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
6✔
1603
    for (String listenerBeanName : listenerBeanNames) {
16✔
1604
      eventMulticaster.addApplicationListenerBean(listenerBeanName);
3✔
1605
    }
1606

1607
    logger.debug("Publish early application events");
4✔
1608
    // Publish early application events now that we finally have a multicaster...
1609
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
3✔
1610
    this.earlyApplicationEvents = null;
3✔
1611
    if (CollectionUtils.isNotEmpty(earlyEventsToProcess)) {
3✔
1612
      for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
10✔
1613
        eventMulticaster.multicastEvent(earlyEvent);
3✔
1614
      }
1✔
1615
    }
1616
  }
1✔
1617

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

1638
  @Override
1639
  public void removeApplicationListener(ApplicationListener<?> listener) {
1640
    Assert.notNull(listener, "ApplicationListener is required");
3✔
1641
    if (applicationEventMulticaster != null) {
3✔
1642
      applicationEventMulticaster.removeApplicationListener(listener);
4✔
1643
    }
1644
    applicationListeners.remove(listener);
5✔
1645
  }
1✔
1646

1647
  /**
1648
   * Finish the initialization of this context's bean factory,
1649
   * initializing all remaining singleton beans.
1650
   */
1651
  protected void finishBeanFactoryInitialization(ConfigurableBeanFactory beanFactory) {
1652
    // Initialize bootstrap executor for this context.
1653
    if (beanFactory.containsBean(BOOTSTRAP_EXECUTOR_BEAN_NAME) &&
7✔
1654
            beanFactory.isTypeMatch(BOOTSTRAP_EXECUTOR_BEAN_NAME, Executor.class)) {
2!
1655
      beanFactory.setBootstrapExecutor(
5✔
1656
              beanFactory.getBean(BOOTSTRAP_EXECUTOR_BEAN_NAME, Executor.class));
2✔
1657
    }
1658

1659
    // Initialize conversion service for this context.
1660
    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME)
7✔
1661
            && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
2!
1662
      beanFactory.setConversionService(
5✔
1663
              beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
2✔
1664
    }
1665

1666
    // Register a default embedded value resolver if no BeanFactoryPostProcessor
1667
    // (such as a PropertySourcesPlaceholderConfigurer bean) registered any before:
1668
    // at this point, primarily for resolution in annotation attribute values.
1669
    if (!beanFactory.hasEmbeddedValueResolver()) {
3✔
1670
      beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolveRequiredPlaceholders(strVal));
9✔
1671
    }
1672

1673
    // Call BeanFactoryInitializer beans early to allow for initializing specific other beans early.
1674
    var initializerNames = beanFactory.getBeanNamesForType(BeanFactoryInitializer.class, false, false);
6✔
1675
    for (String initializerName : initializerNames) {
10!
1676
      beanFactory.getBean(initializerName, BeanFactoryInitializer.class).initialize(beanFactory);
×
1677
    }
1678

1679
    // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
1680
    var weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
6✔
1681
    for (String weaverAwareName : weaverAwareNames) {
10!
1682
      try {
1683
        beanFactory.getBean(weaverAwareName, LoadTimeWeaverAware.class);
×
1684
      }
1685
      catch (BeanNotOfRequiredTypeException ex) {
×
1686
        logger.debug("Failed to initialize LoadTimeWeaverAware bean '{}' due to unexpected type mismatch: {}",
×
1687
                weaverAwareName, ex.getMessage());
×
1688
      }
×
1689
    }
1690

1691
    // Stop using the temporary ClassLoader for type matching.
1692
    beanFactory.setTempClassLoader(null);
3✔
1693

1694
    // Allow for caching all bean definition metadata, not expecting further changes.
1695
    beanFactory.freezeConfiguration();
2✔
1696

1697
    // Instantiate all remaining (non-lazy-init) singletons.
1698
    beanFactory.preInstantiateSingletons();
2✔
1699
  }
1✔
1700

1701
  /**
1702
   * Finish the refresh of this context, invoking the LifecycleProcessor's
1703
   * onRefresh() method and publishing the {@link ContextRefreshedEvent}.
1704
   */
1705
  protected void finishRefresh() {
1706
    // Reset common introspection caches in core infrastructure.
1707
    resetCommonCaches();
2✔
1708

1709
    // Clear context-level resource caches (such as ASM metadata from scanning).
1710
    clearResourceCaches();
2✔
1711

1712
    // Initialize lifecycle processor for this context.
1713
    initLifecycleProcessor();
2✔
1714

1715
    // Propagate refresh to lifecycle processor first.
1716
    getLifecycleProcessor().onRefresh();
3✔
1717

1718
    // Publish the final event.
1719
    publishEvent(new ContextRefreshedEvent(this));
6✔
1720

1721
    applyState(State.STARTED);
3✔
1722
    Duration duration = Duration.between(getStartupDate(), Instant.now());
5✔
1723
    logger.info("Application context startup in {} ms", duration.toMillis());
7✔
1724
  }
1✔
1725

1726
  @Override
1727
  public void clearResourceCaches() {
1728
    super.clearResourceCaches();
2✔
1729
    if (patternResourceLoader instanceof PathMatchingPatternResourceLoader pmprl) {
9✔
1730
      pmprl.clearCache();
2✔
1731
    }
1732
  }
1✔
1733

1734
  //---------------------------------------------------------------------
1735
  // Abstract methods that must be implemented by subclasses
1736
  //---------------------------------------------------------------------
1737

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

1752
  /**
1753
   * Subclasses must implement this method to release their internal bean factory.
1754
   * This method gets invoked by {@link #close()} after all other shutdown work.
1755
   * <p>Should never throw an exception but rather log shutdown failures.
1756
   *
1757
   * @since 4.0
1758
   */
1759
  protected void closeBeanFactory() { }
×
1760

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

1778
  // Object
1779

1780
  /**
1781
   * Return information about this context.
1782
   */
1783
  @Override
1784
  public String toString() {
1785
    return "%s: state: [%s], on startup date: %s, parent: %s".formatted(
8✔
1786
            getDisplayName(), state, startupDate, parent != null ? parent.getDisplayName() : "none");
23✔
1787
  }
1788

1789
}
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