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

TAKETODAY / today-infrastructure / 18901940452

29 Oct 2025 08:40AM UTC coverage: 83.385% (-0.01%) from 83.397%
18901940452

push

github

TAKETODAY
:art:

60820 of 78019 branches covered (77.96%)

Branch coverage included in aggregate %.

143823 of 167400 relevant lines covered (85.92%)

3.66 hits per line

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

82.87
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 org.jspecify.annotations.Nullable;
21

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

224
  /** @since 4.0 */
225

226
  @Nullable
227
  private ExpressionEvaluator expressionEvaluator;
228

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

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

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

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

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

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

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

257
  @Nullable
258
  private BootstrapContext bootstrapContext;
259

260
  @Nullable
261
  private ConfigurableEnvironment environment;
262

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

609
    ConfigurableEnvironment environment = getEnvironment();
3✔
610

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

614
    environment.validateRequiredProperties();
2✔
615

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

741
    // loading some outside beans
742

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

752
  // post-processor
753

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1158
  @Override
1159
  @SuppressWarnings("NullAway")
1160
  public <T> T getBean(Class<T> requiredType, @Nullable Object @Nullable ... args) throws BeansException {
1161
    assertBeanFactoryActive();
2✔
1162
    return getBeanFactory().getBean(requiredType, args);
6✔
1163
  }
1164

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

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

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

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

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

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

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

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

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

1224
  @Override
1225
  public boolean isPrototype(String name) {
1226
    assertBeanFactoryActive();
2✔
1227
    return getBeanFactory().isPrototype(name);
5✔
1228
  }
1229

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

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

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

1250
  @Override
1251
  public boolean containsBean(String name) {
1252
    return getBeanFactory().containsBean(name);
5✔
1253
  }
1254

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

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

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

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

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

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

1291
  @Override
1292
  public String[] getAliases(String name) {
1293
    assertBeanFactoryActive();
2✔
1294
    return getBeanFactory().getAliases(name);
5✔
1295
  }
1296

1297
  // type lookup
1298

1299
  @Override
1300
  public <T> List<T> getBeans(Class<T> requiredType) {
1301
    assertBeanFactoryActive();
×
1302
    return getBeanFactory().getBeans(requiredType);
×
1303
  }
1304

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

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

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

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

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

1335
  @Override
1336
  public String[] getBeanNamesForType(ResolvableType requiredType) {
1337
    assertBeanFactoryActive();
×
1338
    return getBeanFactory().getBeanNamesForType(requiredType);
×
1339
  }
1340

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

1347
  @Override
1348
  public boolean containsBeanDefinition(String beanName) {
1349
    assertBeanFactoryActive();
×
1350
    return getBeanFactory().containsBeanDefinition(beanName);
×
1351
  }
1352

1353
  @Override
1354
  public BeanDefinition getBeanDefinition(String beanName) throws BeansException {
1355
    assertBeanFactoryActive();
×
1356
    return getBeanFactory().getBeanDefinition(beanName);
×
1357
  }
1358

1359
  @Override
1360
  public int getBeanDefinitionCount() {
1361
    assertBeanFactoryActive();
×
1362
    return getBeanFactory().getBeanDefinitionCount();
×
1363
  }
1364

1365
  @Override
1366
  public String[] getBeanDefinitionNames() {
1367
    assertBeanFactoryActive();
×
1368
    return new String[0];
×
1369
  }
1370

1371
  @Override
1372
  public DependencyInjector getInjector() {
1373
    return getBeanFactory().getInjector();
4✔
1374
  }
1375

1376
  //---------------------------------------------------------------------
1377
  // Implementation of Lifecycle interface
1378
  //---------------------------------------------------------------------
1379

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

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

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

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

1404
  @Override
1405
  public boolean isRunning() {
1406
    return this.lifecycleProcessor != null && this.lifecycleProcessor.isRunning();
11!
1407
  }
1408

1409
  // lifecycleProcessor
1410

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

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

1452
  //---------------------------------------------------------------------
1453
  // Implementation of ApplicationEventPublisher interface
1454
  //---------------------------------------------------------------------
1455

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

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

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

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

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

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

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

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

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

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

1596
  protected void registerApplicationListeners() {
1597
    logger.debug("Registering application-listeners");
4✔
1598

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

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

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

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

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

1652
  /**
1653
   * Finish the initialization of this context's bean factory,
1654
   * initializing all remaining singleton beans.
1655
   */
1656
  protected void finishBeanFactoryInitialization(ConfigurableBeanFactory beanFactory) {
1657
    // Mark current thread for singleton instantiation with applied bootstrap locking.
1658
    beanFactory.prepareSingletonBootstrap();
2✔
1659

1660
    // Initialize bootstrap executor for this context.
1661
    if (beanFactory.containsBean(BOOTSTRAP_EXECUTOR_BEAN_NAME) &&
7✔
1662
            beanFactory.isTypeMatch(BOOTSTRAP_EXECUTOR_BEAN_NAME, Executor.class)) {
2!
1663
      beanFactory.setBootstrapExecutor(
5✔
1664
              beanFactory.getBean(BOOTSTRAP_EXECUTOR_BEAN_NAME, Executor.class));
2✔
1665
    }
1666

1667
    // Initialize conversion service for this context.
1668
    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME)
7✔
1669
            && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
2!
1670
      beanFactory.setConversionService(
5✔
1671
              beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
2✔
1672
    }
1673

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

1681
    // Call BeanFactoryInitializer beans early to allow for initializing specific other beans early.
1682
    var initializerNames = beanFactory.getBeanNamesForType(BeanFactoryInitializer.class, false, false);
6✔
1683
    for (String initializerName : initializerNames) {
10!
1684
      beanFactory.getBean(initializerName, BeanFactoryInitializer.class).initialize(beanFactory);
×
1685
    }
1686

1687
    // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
1688
    var weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
6✔
1689
    for (String weaverAwareName : weaverAwareNames) {
16✔
1690
      try {
1691
        beanFactory.getBean(weaverAwareName, LoadTimeWeaverAware.class);
5✔
1692
      }
1693
      catch (BeanNotOfRequiredTypeException ex) {
×
1694
        logger.debug("Failed to initialize LoadTimeWeaverAware bean '{}' due to unexpected type mismatch: {}",
×
1695
                weaverAwareName, ex.getMessage());
×
1696
      }
1✔
1697
    }
1698

1699
    // Stop using the temporary ClassLoader for type matching.
1700
    beanFactory.setTempClassLoader(null);
3✔
1701

1702
    // Allow for caching all bean definition metadata, not expecting further changes.
1703
    beanFactory.freezeConfiguration();
2✔
1704

1705
    // Instantiate all remaining (non-lazy-init) singletons.
1706
    beanFactory.preInstantiateSingletons();
2✔
1707
  }
1✔
1708

1709
  /**
1710
   * Finish the refresh of this context, invoking the LifecycleProcessor's
1711
   * onRefresh() method and publishing the {@link ContextRefreshedEvent}.
1712
   */
1713
  protected void finishRefresh() {
1714
    // Reset common introspection caches in core infrastructure.
1715
    resetCommonCaches();
2✔
1716

1717
    // Clear context-level resource caches (such as ASM metadata from scanning).
1718
    clearResourceCaches();
2✔
1719

1720
    // Initialize lifecycle processor for this context.
1721
    initLifecycleProcessor();
2✔
1722

1723
    // Propagate refresh to lifecycle processor first.
1724
    getLifecycleProcessor().onRefresh();
3✔
1725

1726
    // Publish the final event.
1727
    publishEvent(new ContextRefreshedEvent(this));
6✔
1728

1729
    applyState(State.STARTED);
3✔
1730
    Duration duration = Duration.between(getStartupDate(), Instant.now());
5✔
1731
    logger.info("Application context startup in {} ms", duration.toMillis());
7✔
1732
  }
1✔
1733

1734
  @Override
1735
  public void clearResourceCaches() {
1736
    super.clearResourceCaches();
2✔
1737
    if (patternResourceLoader instanceof PathMatchingPatternResourceLoader pmprl) {
9✔
1738
      pmprl.clearCache();
2✔
1739
    }
1740
  }
1✔
1741

1742
  //---------------------------------------------------------------------
1743
  // Abstract methods that must be implemented by subclasses
1744
  //---------------------------------------------------------------------
1745

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

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

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

1787
  // Object
1788

1789
  /**
1790
   * Return information about this context.
1791
   */
1792
  @Override
1793
  public String toString() {
1794
    return "%s: state: [%s], on startup date: %s, parent: %s".formatted(
8✔
1795
            getDisplayName(), state, startupDate, parent != null ? parent.getDisplayName() : "none");
23✔
1796
  }
1797

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