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

TAKETODAY / today-infrastructure / 17553285606

08 Sep 2025 01:57PM UTC coverage: 81.853%. Remained the same
17553285606

push

github

TAKETODAY
:art:

59722 of 77938 branches covered (76.63%)

Branch coverage included in aggregate %.

141165 of 167486 relevant lines covered (84.28%)

3.6 hits per line

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

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

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

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

189
  protected final Logger logger = LoggerFactory.getLogger(getClass());
5✔
190

191
  private final ArrayList<BeanFactoryPostProcessor> factoryPostProcessors = new ArrayList<>();
5✔
192

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

196
  /** @since 4.0 */
197
  private final PatternResourceLoader patternResourceLoader = getPatternResourceLoader();
4✔
198

199
  /** Flag that indicates whether this context is currently active. */
200
  private final AtomicBoolean active = new AtomicBoolean();
5✔
201

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

205
  /** Synchronization lock for "refresh" and "close". */
206
  private final ReentrantLock startupShutdownLock = new ReentrantLock();
5✔
207

208
  private Instant startupDate = Instant.now();
3✔
209

210
  // @since 2.1.5
211
  private State state = State.NONE;
3✔
212

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

216
  /** Display name. */
217
  private String displayName = ObjectUtils.identityToString(this);
4✔
218

219
  /** Parent context. @since 4.0 */
220
  @Nullable
221
  private ApplicationContext parent;
222

223
  /** @since 4.0 */
224

225
  @Nullable
226
  private ExpressionEvaluator expressionEvaluator;
227

228
  /** Reference to the JVM shutdown hook, if registered. */
229
  @Nullable
230
  private Thread shutdownHook;
231

232
  /** Currently active startup/shutdown thread. */
233
  @Nullable
234
  private volatile Thread startupShutdownThread;
235

236
  /** LifecycleProcessor for managing the lifecycle of beans within this context. @since 4.0 */
237
  @Nullable
238
  private LifecycleProcessor lifecycleProcessor;
239

240
  /** Helper class used in event publishing. @since 4.0 */
241
  @Nullable
242
  private ApplicationEventMulticaster applicationEventMulticaster;
243

244
  /** Local listeners registered before refresh. @since 4.0 */
245
  @Nullable
246
  private Set<ApplicationListener<?>> earlyApplicationListeners;
247

248
  /** ApplicationEvents published before the multicaster setup. @since 4.0 */
249
  @Nullable
250
  private Set<ApplicationEvent> earlyApplicationEvents;
251

252
  /** MessageSource we delegate our implementation of this interface to. @since 4.0 */
253
  @Nullable
254
  private MessageSource messageSource;
255

256
  @Nullable
257
  private BootstrapContext bootstrapContext;
258

259
  @Nullable
260
  private ConfigurableEnvironment environment;
261

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

608
    ConfigurableEnvironment environment = getEnvironment();
3✔
609

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

613
    environment.validateRequiredProperties();
2✔
614

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

740
    // loading some outside beans
741

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

751
  // post-processor
752

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1060
  //---------------------------------------------------------------------
1061
  // Implementation of ConfigurableApplicationContext interface
1062
  //---------------------------------------------------------------------
1063

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

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

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

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

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

1112
    factoryPostProcessors.add(postProcessor);
5✔
1113
  }
1✔
1114

1115
  //---------------------------------------------------------------------
1116
  // Implementation of BeanFactory interface
1117
  //---------------------------------------------------------------------
1118

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1294
  // type lookup
1295

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

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

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

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

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

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

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

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

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

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

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

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

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

1373
  //---------------------------------------------------------------------
1374
  // Implementation of Lifecycle interface
1375
  //---------------------------------------------------------------------
1376

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

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

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

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

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

1406
  // lifecycleProcessor
1407

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

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

1449
  //---------------------------------------------------------------------
1450
  // Implementation of ApplicationEventPublisher interface
1451
  //---------------------------------------------------------------------
1452

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1714
    // Initialize lifecycle processor for this context.
1715
    initLifecycleProcessor();
2✔
1716

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

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

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

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

1736
  //---------------------------------------------------------------------
1737
  // Abstract methods that must be implemented by subclasses
1738
  //---------------------------------------------------------------------
1739

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

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

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

1781
  // Object
1782

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

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