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

TAKETODAY / today-infrastructure / 20224960533

15 Dec 2025 08:11AM UTC coverage: 84.388% (-0.02%) from 84.404%
20224960533

push

github

TAKETODAY
:white_check_mark: 在测试中排除 jacoco 初始化方法以避免干扰

61869 of 78367 branches covered (78.95%)

Branch coverage included in aggregate %.

145916 of 167860 relevant lines covered (86.93%)

3.71 hits per line

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

82.8
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
        // Stop already started Lifecycle beans to avoid dangling resources.
582
        if (this.lifecycleProcessor != null && this.lifecycleProcessor.isRunning()) {
7✔
583
          try {
584
            this.lifecycleProcessor.stop();
3✔
585
          }
586
          catch (Throwable ex2) {
×
587
            logger.warn("Exception thrown from LifecycleProcessor on cancelled refresh", ex2);
×
588
          }
1✔
589
        }
590

591
        // Destroy already created singletons to avoid dangling resources.
592
        destroyBeans();
2✔
593

594
        // Reset 'active' flag.
595
        cancelRefresh(ex);
3✔
596

597
        // Propagate exception to caller.
598
        throw ex;
2✔
599
      }
1✔
600
    }
601
    finally {
602
      this.startupShutdownThread = null;
3✔
603
      this.startupShutdownLock.unlock();
3✔
604
    }
605
  }
1✔
606

607
  /**
608
   * Prepare to load context
609
   */
610
  protected void prepareRefresh() {
611
    this.startupDate = Instant.now();
3✔
612
    this.closed.set(false);
4✔
613
    this.active.set(true);
4✔
614
    applyState(State.STARTING);
3✔
615
    ApplicationContextHolder.register(this); // @since 4.0
3✔
616

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

619
    ConfigurableEnvironment environment = getEnvironment();
3✔
620

621
    // Initialize any placeholder property sources in the context environment.
622
    initPropertySources();
2✔
623

624
    environment.validateRequiredProperties();
2✔
625

626
    // Store pre-refresh ApplicationListeners...
627
    if (this.earlyApplicationListeners == null) {
3✔
628
      this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
8✔
629
    }
630
    else {
631
      // Reset local application listeners to pre-refresh state.
632
      this.applicationListeners.clear();
3✔
633
      this.applicationListeners.addAll(this.earlyApplicationListeners);
6✔
634
    }
635

636
    // Allow for the collection of early ApplicationEvents,
637
    // to be published once the multicaster is available...
638
    this.earlyApplicationEvents = new LinkedHashSet<>();
5✔
639

640
    if (logger.isDebugEnabled()) {
4✔
641
      if (logger.isTraceEnabled()) {
4!
642
        logger.trace("Refreshing {}", this);
×
643
      }
644
      else {
645
        logger.debug("Refreshing {}", getDisplayName());
6✔
646
      }
647
    }
648
  }
1✔
649

650
  /**
651
   * <p>
652
   * load properties files or itself strategies
653
   */
654
  protected void initPropertySources() throws ApplicationContextException {
655
    // for subclasses loading properties or prepare property-source
656
  }
1✔
657

658
  /**
659
   * Register Framework Beans
660
   */
661
  protected void registerFrameworkComponents(ConfigurableBeanFactory beanFactory) {
662
    logger.debug("Registering framework components");
4✔
663

664
    BootstrapContext bootstrapContext = getBootstrapContext();
3✔
665
    beanFactory.registerSingleton(getDependencyInjector(bootstrapContext));
5✔
666

667
    if (!beanFactory.containsLocalBean(BootstrapContext.BEAN_NAME)) {
4!
668
      beanFactory.registerSingleton(BootstrapContext.BEAN_NAME, bootstrapContext);
4✔
669
    }
670
    // Register default environment beans.
671
    if (!beanFactory.containsLocalBean(Environment.ENVIRONMENT_BEAN_NAME)) {
4!
672
      beanFactory.registerSingleton(Environment.ENVIRONMENT_BEAN_NAME, getEnvironment());
5✔
673
    }
674
    if (!beanFactory.containsLocalBean(Environment.SYSTEM_PROPERTIES_BEAN_NAME)) {
4!
675
      beanFactory.registerSingleton(Environment.SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
6✔
676
    }
677
    if (!beanFactory.containsLocalBean(Environment.SYSTEM_ENVIRONMENT_BEAN_NAME)) {
4!
678
      beanFactory.registerSingleton(Environment.SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
6✔
679
    }
680
  }
1✔
681

682
  private DependencyInjector getDependencyInjector(BootstrapContext bootstrapContext) {
683
    DependencyInjector injector = getInjector();
3✔
684
    var strategies = TodayStrategies.find(DependencyResolvingStrategy.class, getClassLoader(), bootstrapContext);
6✔
685
    injector.setResolvingStrategies(new DependencyResolvingStrategies(strategies));
6✔
686
    return injector;
2✔
687
  }
688

689
  /**
690
   * Initialization singletons that has already in context
691
   */
692
  protected void onRefresh() {
693
    // sub-classes Initialization
694
  }
1✔
695

696
  /**
697
   * Tell the subclass to refresh the internal bean factory.
698
   *
699
   * @return the fresh BeanFactory instance
700
   * @see #refreshBeanFactory()
701
   * @see #getBeanFactory()
702
   * @since 4.0
703
   */
704
  protected ConfigurableBeanFactory obtainFreshBeanFactory() {
705
    refreshBeanFactory();
2✔
706
    return getBeanFactory();
3✔
707
  }
708

709
  /**
710
   * Configure the factory's standard context characteristics,
711
   * such as the context's ClassLoader and post-processors.
712
   *
713
   * @param beanFactory the BeanFactory to configure
714
   */
715
  protected void prepareBeanFactory(ConfigurableBeanFactory beanFactory) {
716
    logger.debug("Preparing bean-factory: {}", beanFactory);
5✔
717
    // Tell the internal bean factory to use the context's class loader etc.
718
    ClassLoader classLoader = getClassLoader();
3✔
719
    beanFactory.setBeanClassLoader(classLoader);
3✔
720
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
7✔
721
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
8✔
722

723
    // Configure the bean factory with context callbacks.
724
    beanFactory.addBeanPostProcessor(new ContextAwareProcessor(this, getBootstrapContext()));
8✔
725
    // Register early post-processor for detecting inner beans as ApplicationListeners.
726
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
6✔
727

728
    // Detect a LoadTimeWeaver and prepare for weaving, if found.
729
    if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
6!
730
      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
×
731
      // Set a temporary ClassLoader for type matching.
732
      beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
×
733
    }
734

735
    // @since 4.0
736
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
3✔
737
    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
3✔
738
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
3✔
739
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
3✔
740
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
3✔
741
    beanFactory.ignoreDependencyInterface(BootstrapContextAware.class);
3✔
742
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
3✔
743

744
    // BeanFactory interface not registered as resolvable type in a plain factory.
745
    // MessageSource registered (and found for autowiring) as a bean.
746
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
4✔
747
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
4✔
748
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
4✔
749
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);
4✔
750

751
    // loading some outside beans
752

753
    BootstrapContext bootstrapContext = getBootstrapContext();
3✔
754
    var strategies = TodayStrategies.find(BeanDefinitionLoader.class, classLoader, bootstrapContext);
5✔
755
    if (!strategies.isEmpty()) {
3!
756
      for (BeanDefinitionLoader loader : strategies) {
×
757
        loader.loadBeanDefinitions(bootstrapContext);
×
758
      }
×
759
    }
760
  }
1✔
761

762
  // post-processor
763

764
  /**
765
   * Modify the application context's internal bean factory after its standard
766
   * initialization. The initial definition resources will have been loaded but no
767
   * post-processors will have run and no derived bean definitions will have been
768
   * registered, and most importantly, no beans will have been instantiated yet.
769
   * <p>This template method allows for registering special BeanPostProcessors
770
   * etc in certain AbstractApplicationContext subclasses.
771
   *
772
   * @param beanFactory the bean factory used by the application context
773
   */
774
  protected void postProcessBeanFactory(ConfigurableBeanFactory beanFactory) {
775
  }
1✔
776

777
  /**
778
   * Instantiate and invoke all registered BeanFactoryPostProcessor beans,
779
   * respecting explicit order if given.
780
   * <p>Must be called before singleton instantiation.
781
   */
782
  protected void invokeBeanFactoryPostProcessors(ConfigurableBeanFactory beanFactory) {
783
    logger.debug("Invoking bean-factory-post-processors");
4✔
784
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, factoryPostProcessors);
4✔
785

786
    // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
787
    // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
788
    if (!NativeDetector.inNativeImage()
3✔
789
            && beanFactory.getTempClassLoader() == null
4!
790
            && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
2✔
791
      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
6✔
792
      beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
7✔
793
    }
794
  }
1✔
795

796
  /**
797
   * Instantiate and register all BeanPostProcessor beans,
798
   * respecting explicit order if given.
799
   * <p>Must be called before any instantiation of application beans.
800
   */
801
  protected void registerBeanPostProcessors(ConfigurableBeanFactory beanFactory) {
802
    logger.debug("Registering bean-post-processors");
4✔
803
    PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
3✔
804
  }
1✔
805

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

838
  /**
839
   * Cancel this context's refresh attempt, after an exception got thrown.
840
   *
841
   * @param ex the exception that led to the cancellation
842
   */
843
  protected void cancelRefresh(Throwable ex) {
844
    this.active.set(false);
4✔
845

846
    // Reset common introspection caches in core infrastructure.
847
    resetCommonCaches();
2✔
848
  }
1✔
849

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

865
      try {
866
        // Publish shutdown event.
867
        publishEvent(new ContextClosedEvent(this));
6✔
868
      }
869
      catch (Throwable ex) {
×
870
        logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
×
871
      }
1✔
872

873
      // Stop all Lifecycle beans, to avoid delays during individual destruction.
874
      if (lifecycleProcessor != null) {
3✔
875
        try {
876
          lifecycleProcessor.onClose();
3✔
877
        }
878
        catch (Throwable ex) {
×
879
          logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
×
880
        }
1✔
881
      }
882
      // Destroy all cached singletons in the context's BeanFactory.
883
      destroyBeans();
2✔
884

885
      // Close the state of this context itself.
886
      closeBeanFactory();
2✔
887

888
      // Let subclasses do some final clean-up if they wish...
889
      onClose();
2✔
890

891
      // Reset common introspection caches to avoid class reference leaks.
892
      resetCommonCaches();
2✔
893

894
      // Reset local application listeners to pre-refresh state.
895
      if (earlyApplicationListeners != null) {
3!
896
        applicationListeners.clear();
3✔
897
        applicationListeners.addAll(earlyApplicationListeners);
6✔
898
      }
899

900
      // Reset internal delegates.
901
      this.applicationEventMulticaster = null;
3✔
902
      this.messageSource = null;
3✔
903
      this.lifecycleProcessor = null;
3✔
904

905
      // Switch to inactive.
906
      active.set(false);
4✔
907
    }
908
  }
1✔
909

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

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

962
      // Interrupted but still waiting: very likely a System.exit call
963
      return activeThread.getState() == Thread.State.WAITING;
×
964
    }
965
    return false;
2✔
966
  }
967

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

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

1023
  /**
1024
   * Template method which can be overridden to add context-specific shutdown work.
1025
   * The default implementation is empty.
1026
   * <p>Called at the end of {@link #doClose}'s shutdown procedure, after
1027
   * this context's BeanFactory has been closed. If custom shutdown logic
1028
   * needs to execute while the BeanFactory is still active, override
1029
   * the {@link #destroyBeans()} method instead.
1030
   *
1031
   * @since 4.0
1032
   */
1033
  protected void onClose() {
1034
    // For subclasses: do nothing by default.
1035
  }
1✔
1036

1037
  @Override
1038
  public boolean isClosed() {
1039
    return this.closed.get();
4✔
1040
  }
1041

1042
  @Override
1043
  public boolean isActive() {
1044
    return active.get();
4✔
1045
  }
1046

1047
  @Override
1048
  @SuppressWarnings("unchecked")
1049
  public <T> T unwrapFactory(Class<T> requiredType) {
1050
    ConfigurableBeanFactory beanFactory = getBeanFactory();
3✔
1051
    if (requiredType.isInstance(beanFactory)) {
4!
1052
      return (T) beanFactory;
2✔
1053
    }
1054
    throw new IllegalArgumentException("bean factory must be a " + requiredType);
×
1055
  }
1056

1057
  @Override
1058
  public State getState() {
1059
    return state;
3✔
1060
  }
1061

1062
  protected void applyState(State state) {
1063
    this.state = state;
3✔
1064
  }
1✔
1065

1066
  @Override
1067
  public Instant getStartupDate() {
1068
    return startupDate;
3✔
1069
  }
1070

1071
  //---------------------------------------------------------------------
1072
  // Implementation of ConfigurableApplicationContext interface
1073
  //---------------------------------------------------------------------
1074

1075
  /**
1076
   * Set the parent of this application context.
1077
   * <p>The parent {@linkplain ApplicationContext#getEnvironment() environment} is
1078
   * {@linkplain ConfigurableEnvironment#merge(ConfigurableEnvironment) merged} with
1079
   * this (child) application context environment if the parent is non-{@code null} and
1080
   * its environment is an instance of {@link ConfigurableEnvironment}.
1081
   *
1082
   * @see ConfigurableEnvironment#merge(ConfigurableEnvironment)
1083
   */
1084
  @Override
1085
  public void setParent(@Nullable ApplicationContext parent) {
1086
    this.parent = parent;
3✔
1087
    if (parent != null) {
2✔
1088
      Environment parentEnvironment = parent.getEnvironment();
3✔
1089
      if (parentEnvironment instanceof ConfigurableEnvironment) {
3!
1090
        getEnvironment().merge((ConfigurableEnvironment) parentEnvironment);
5✔
1091
      }
1092
    }
1093
  }
1✔
1094

1095
  @Override
1096
  public ConfigurableEnvironment getEnvironment() {
1097
    ConfigurableEnvironment environment = this.environment;
3✔
1098
    if (environment == null) {
2✔
1099
      environment = createEnvironment();
3✔
1100
      this.environment = environment;
3✔
1101
    }
1102
    return environment;
2✔
1103
  }
1104

1105
  /**
1106
   * Create and return a new {@link StandardEnvironment}.
1107
   * <p>Subclasses may override this method in order to supply
1108
   * a custom {@link ConfigurableEnvironment} implementation.
1109
   */
1110
  protected ConfigurableEnvironment createEnvironment() {
1111
    return new StandardEnvironment();
4✔
1112
  }
1113

1114
  @Override
1115
  public void setEnvironment(ConfigurableEnvironment environment) {
1116
    this.environment = environment;
3✔
1117
  }
1✔
1118

1119
  @Override
1120
  public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor) {
1121
    Assert.notNull(postProcessor, "BeanFactoryPostProcessor is required");
3✔
1122

1123
    factoryPostProcessors.add(postProcessor);
5✔
1124
  }
1✔
1125

1126
  //---------------------------------------------------------------------
1127
  // Implementation of BeanFactory interface
1128
  //---------------------------------------------------------------------
1129

1130
  /**
1131
   * Assert that this context's BeanFactory is currently active,
1132
   * throwing an {@link IllegalStateException} if it isn't.
1133
   * <p>Invoked by all {@link BeanFactory} delegation methods that depend
1134
   * on an active context, i.e. in particular all bean accessor methods.
1135
   */
1136
  protected void assertBeanFactoryActive() {
1137
    if (!active.get()) {
4✔
1138
      if (closed.get()) {
4✔
1139
        throw new IllegalStateException(getDisplayName() + " has been closed already");
7✔
1140
      }
1141
      else {
1142
        throw new IllegalStateException(getDisplayName() + " has not been refreshed yet");
7✔
1143
      }
1144
    }
1145
  }
1✔
1146

1147
  @Nullable
1148
  @Override
1149
  public Object getBean(String name) {
1150
    assertBeanFactoryActive();
2✔
1151
    return getBeanFactory().getBean(name);
5✔
1152
  }
1153

1154
  @Nullable
1155
  @Override
1156
  @SuppressWarnings("NullAway")
1157
  public Object getBean(String name, @Nullable Object @Nullable ... args) throws BeansException {
1158
    assertBeanFactoryActive();
×
1159
    return getBeanFactory().getBean(name, args);
×
1160
  }
1161

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

1168
  @Override
1169
  @SuppressWarnings("NullAway")
1170
  public <T> T getBean(Class<T> requiredType, @Nullable Object @Nullable ... args) throws BeansException {
1171
    assertBeanFactoryActive();
2✔
1172
    return getBeanFactory().getBean(requiredType, args);
6✔
1173
  }
1174

1175
  @Override
1176
  public <T> T getBean(String name, Class<T> requiredType) {
1177
    assertBeanFactoryActive();
2✔
1178
    return getBeanFactory().getBean(name, requiredType);
6✔
1179
  }
1180

1181
  @Nullable
1182
  @Override
1183
  public <A extends Annotation> A findSynthesizedAnnotation(String beanName, Class<A> annotationType) {
1184
    assertBeanFactoryActive();
×
1185
    return getBeanFactory().findSynthesizedAnnotation(beanName, annotationType);
×
1186
  }
1187

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

1195
  @Override
1196
  public <A extends Annotation> MergedAnnotation<A> findAnnotationOnBean(
1197
          String beanName, Class<A> annotationType, boolean allowFactoryBeanInit)
1198
          throws NoSuchBeanDefinitionException {
1199
    assertBeanFactoryActive();
×
1200
    return getBeanFactory().findAnnotationOnBean(beanName, annotationType, allowFactoryBeanInit);
×
1201
  }
1202

1203
  @Override
1204
  public <A extends Annotation> Set<A> findAllAnnotationsOnBean(
1205
          String beanName, Class<A> annotationType, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException {
1206
    assertBeanFactoryActive();
×
1207
    return getBeanFactory().findAllAnnotationsOnBean(beanName, annotationType, allowFactoryBeanInit);
×
1208
  }
1209

1210
  @Override
1211
  public <T> List<T> getAnnotatedBeans(Class<? extends Annotation> annotationType) {
1212
    assertBeanFactoryActive();
×
1213
    return getBeanFactory().getAnnotatedBeans(annotationType);
×
1214
  }
1215

1216
  @Override
1217
  public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) {
1218
    assertBeanFactoryActive();
2✔
1219
    return getBeanFactory().getBeansWithAnnotation(annotationType);
5✔
1220
  }
1221

1222
  @Override
1223
  public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType, boolean includeNonSingletons) {
1224
    assertBeanFactoryActive();
×
1225
    return getBeanFactory().getBeansWithAnnotation(annotationType, includeNonSingletons);
×
1226
  }
1227

1228
  @Override
1229
  public boolean isSingleton(String name) {
1230
    assertBeanFactoryActive();
2✔
1231
    return getBeanFactory().isSingleton(name);
5✔
1232
  }
1233

1234
  @Override
1235
  public boolean isPrototype(String name) {
1236
    assertBeanFactoryActive();
2✔
1237
    return getBeanFactory().isPrototype(name);
5✔
1238
  }
1239

1240
  @Nullable
1241
  @Override
1242
  public Class<?> getType(String name) {
1243
    assertBeanFactoryActive();
2✔
1244
    return getBeanFactory().getType(name);
5✔
1245
  }
1246

1247
  @Nullable
1248
  @Override
1249
  public Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException {
1250
    assertBeanFactoryActive();
×
1251
    return getBeanFactory().getType(name, allowFactoryBeanInit);
×
1252
  }
1253

1254
  @Override
1255
  public String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType) {
1256
    assertBeanFactoryActive();
2✔
1257
    return getBeanFactory().getBeanNamesForAnnotation(annotationType);
5✔
1258
  }
1259

1260
  @Override
1261
  public boolean containsBean(String name) {
1262
    return getBeanFactory().containsBean(name);
5✔
1263
  }
1264

1265
  @Override
1266
  public boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException {
1267
    assertBeanFactoryActive();
2✔
1268
    return getBeanFactory().isTypeMatch(name, typeToMatch);
6✔
1269
  }
1270

1271
  @Override
1272
  public boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException {
1273
    assertBeanFactoryActive();
×
1274
    return getBeanFactory().isTypeMatch(name, typeToMatch);
×
1275
  }
1276

1277
  @Override
1278
  public <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType) {
1279
    assertBeanFactoryActive();
2✔
1280
    return getBeanFactory().getBeanProvider(requiredType);
5✔
1281
  }
1282

1283
  @Override
1284
  public <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType) {
1285
    assertBeanFactoryActive();
2✔
1286
    return getBeanFactory().getBeanProvider(requiredType);
5✔
1287
  }
1288

1289
  @Override
1290
  public <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType, boolean allowEagerInit) {
1291
    assertBeanFactoryActive();
×
1292
    return getBeanFactory().getBeanProvider(requiredType, allowEagerInit);
×
1293
  }
1294

1295
  @Override
1296
  public <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType, boolean allowEagerInit) {
1297
    assertBeanFactoryActive();
×
1298
    return getBeanFactory().getBeanProvider(requiredType, allowEagerInit);
×
1299
  }
1300

1301
  @Override
1302
  public String[] getAliases(String name) {
1303
    assertBeanFactoryActive();
2✔
1304
    return getBeanFactory().getAliases(name);
5✔
1305
  }
1306

1307
  // type lookup
1308

1309
  @Override
1310
  public <T> List<T> getBeans(Class<T> requiredType) {
1311
    assertBeanFactoryActive();
×
1312
    return getBeanFactory().getBeans(requiredType);
×
1313
  }
1314

1315
  @Override
1316
  public String[] getBeanNamesForType(@Nullable Class<?> type) {
1317
    assertBeanFactoryActive();
2✔
1318
    return getBeanFactory().getBeanNamesForType(type);
5✔
1319
  }
1320

1321
  @Override
1322
  public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
1323
    assertBeanFactoryActive();
2✔
1324
    return getBeanFactory().getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
7✔
1325
  }
1326

1327
  @Override
1328
  public <T> Map<String, T> getBeansOfType(Class<T> type) {
1329
    assertBeanFactoryActive();
2✔
1330
    return getBeanFactory().getBeansOfType(type);
5✔
1331
  }
1332

1333
  @Override
1334
  public <T> Map<String, T> getBeansOfType(@Nullable Class<T> requiredType, boolean includeNonSingletons, boolean allowEagerInit) {
1335
    assertBeanFactoryActive();
2✔
1336
    return getBeanFactory().getBeansOfType(requiredType, includeNonSingletons, allowEagerInit);
7✔
1337
  }
1338

1339
  @Override
1340
  public <T> Map<String, T> getBeansOfType(ResolvableType requiredType, boolean includeNonSingletons, boolean allowEagerInit) {
1341
    assertBeanFactoryActive();
×
1342
    return getBeanFactory().getBeansOfType(requiredType, includeNonSingletons, allowEagerInit);
×
1343
  }
1344

1345
  @Override
1346
  public String[] getBeanNamesForType(ResolvableType requiredType) {
1347
    assertBeanFactoryActive();
×
1348
    return getBeanFactory().getBeanNamesForType(requiredType);
×
1349
  }
1350

1351
  @Override
1352
  public String[] getBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
1353
    assertBeanFactoryActive();
×
1354
    return getBeanFactory().getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
×
1355
  }
1356

1357
  @Override
1358
  public boolean containsBeanDefinition(String beanName) {
1359
    assertBeanFactoryActive();
×
1360
    return getBeanFactory().containsBeanDefinition(beanName);
×
1361
  }
1362

1363
  @Override
1364
  public BeanDefinition getBeanDefinition(String beanName) throws BeansException {
1365
    assertBeanFactoryActive();
×
1366
    return getBeanFactory().getBeanDefinition(beanName);
×
1367
  }
1368

1369
  @Override
1370
  public int getBeanDefinitionCount() {
1371
    assertBeanFactoryActive();
×
1372
    return getBeanFactory().getBeanDefinitionCount();
×
1373
  }
1374

1375
  @Override
1376
  public String[] getBeanDefinitionNames() {
1377
    assertBeanFactoryActive();
×
1378
    return new String[0];
×
1379
  }
1380

1381
  @Override
1382
  public DependencyInjector getInjector() {
1383
    return getBeanFactory().getInjector();
4✔
1384
  }
1385

1386
  //---------------------------------------------------------------------
1387
  // Implementation of Lifecycle interface
1388
  //---------------------------------------------------------------------
1389

1390
  @Override
1391
  public void start() {
1392
    getLifecycleProcessor().start();
3✔
1393
    publishEvent(new ContextStartedEvent(this));
6✔
1394
  }
1✔
1395

1396
  @Override
1397
  public void stop() {
1398
    getLifecycleProcessor().stop();
3✔
1399
    publishEvent(new ContextStoppedEvent(this));
6✔
1400
  }
1✔
1401

1402
  @Override
1403
  public void restart() {
1404
    getLifecycleProcessor().onRestart();
3✔
1405
    publishEvent(new ContextRestartedEvent(this));
6✔
1406
  }
1✔
1407

1408
  @Override
1409
  public void pause() {
1410
    getLifecycleProcessor().onPause();
3✔
1411
    publishEvent(new ContextPausedEvent(this));
6✔
1412
  }
1✔
1413

1414
  @Override
1415
  public boolean isRunning() {
1416
    return this.lifecycleProcessor != null && this.lifecycleProcessor.isRunning();
11!
1417
  }
1418

1419
  // lifecycleProcessor
1420

1421
  /**
1422
   * Initialize the LifecycleProcessor.
1423
   * Uses DefaultLifecycleProcessor if none defined in the context.
1424
   *
1425
   * @see DefaultLifecycleProcessor
1426
   */
1427
  protected void initLifecycleProcessor() {
1428
    if (lifecycleProcessor == null) {
3✔
1429
      ConfigurableBeanFactory beanFactory = getBeanFactory();
3✔
1430
      if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
4✔
1431
        this.lifecycleProcessor = beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
7✔
1432
        if (logger.isTraceEnabled()) {
4!
1433
          logger.trace("Using LifecycleProcessor [{}]", lifecycleProcessor);
×
1434
        }
1435
      }
1436
      else {
1437
        DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
4✔
1438
        defaultProcessor.setBeanFactory(beanFactory);
3✔
1439
        this.lifecycleProcessor = defaultProcessor;
3✔
1440
        beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
5✔
1441
        if (logger.isTraceEnabled()) {
4!
1442
          logger.trace("No '{}' bean, using [{}]", LIFECYCLE_PROCESSOR_BEAN_NAME, lifecycleProcessor.getClass().getSimpleName());
×
1443
        }
1444
      }
1445
    }
1446
  }
1✔
1447

1448
  /**
1449
   * Return the internal LifecycleProcessor used by the context.
1450
   *
1451
   * @return the internal LifecycleProcessor (never {@code null})
1452
   * @throws IllegalStateException if the context has not been initialized yet
1453
   */
1454
  public LifecycleProcessor getLifecycleProcessor() throws IllegalStateException {
1455
    if (this.lifecycleProcessor == null) {
3!
1456
      throw new IllegalStateException(
×
1457
              "LifecycleProcessor not initialized - call 'refresh' before invoking lifecycle methods via the context: " + this);
1458
    }
1459
    return this.lifecycleProcessor;
3✔
1460
  }
1461

1462
  //---------------------------------------------------------------------
1463
  // Implementation of ApplicationEventPublisher interface
1464
  //---------------------------------------------------------------------
1465

1466
  /**
1467
   * Return the internal ApplicationEventMulticaster used by the context.
1468
   *
1469
   * @return the internal ApplicationEventMulticaster (never {@code null})
1470
   * @throws IllegalStateException if the context has not been initialized yet
1471
   */
1472
  public ApplicationEventMulticaster getApplicationEventMulticaster() throws IllegalStateException {
1473
    if (this.applicationEventMulticaster == null) {
3!
1474
      throw new IllegalStateException(
×
1475
              "ApplicationEventMulticaster not initialized - call 'refresh' before multicasting events via the context: " + this);
1476
    }
1477
    return this.applicationEventMulticaster;
3✔
1478
  }
1479

1480
  /**
1481
   * Initialize the ApplicationEventMulticaster.
1482
   * Uses SimpleApplicationEventMulticaster if none defined in the context.
1483
   *
1484
   * @see SimpleApplicationEventMulticaster
1485
   */
1486
  protected void initApplicationEventMulticaster() {
1487
    ConfigurableBeanFactory beanFactory = getBeanFactory();
3✔
1488
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
4✔
1489
      this.applicationEventMulticaster =
4✔
1490
              beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
3✔
1491
      if (logger.isTraceEnabled()) {
4!
1492
        logger.trace("Using ApplicationEventMulticaster [{}]", applicationEventMulticaster);
×
1493
      }
1494
    }
1495
    else {
1496
      this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
6✔
1497
      beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, applicationEventMulticaster);
5✔
1498
      if (logger.isTraceEnabled()) {
4!
1499
        logger.trace("No '{}' bean, using [{}]",
×
1500
                APPLICATION_EVENT_MULTICASTER_BEAN_NAME, applicationEventMulticaster.getClass().getSimpleName());
×
1501
      }
1502
    }
1503
  }
1✔
1504

1505
  /**
1506
   * Return the list of statically specified ApplicationListeners.
1507
   */
1508
  public Collection<ApplicationListener<?>> getApplicationListeners() {
1509
    return this.applicationListeners;
3✔
1510
  }
1511

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

1526
  /**
1527
   * Publish the given event to all listeners.
1528
   * <p>Note: Listeners get initialized after the MessageSource, to be able
1529
   * to access it within listener implementations. Thus, MessageSource
1530
   * implementations cannot publish events.
1531
   *
1532
   * @param event the event to publish (may be an {@link ApplicationEvent}
1533
   * or a payload object to be turned into a {@link PayloadApplicationEvent})
1534
   */
1535
  @Override
1536
  public void publishEvent(Object event) {
1537
    publishEvent(event, null);
4✔
1538
  }
1✔
1539

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

1562
    // Decorate event as an ApplicationEvent if necessary
1563
    ApplicationEvent applicationEvent;
1564
    if (event instanceof ApplicationEvent applEvent) {
6✔
1565
      applicationEvent = applEvent;
2✔
1566
      eventType = typeHint;
3✔
1567
    }
1568
    else {
1569
      ResolvableType payloadType = null;
2✔
1570
      if (typeHint != null && ApplicationEvent.class.isAssignableFrom(typeHint.toClass())) {
7✔
1571
        eventType = typeHint;
3✔
1572
      }
1573
      else {
1574
        payloadType = typeHint;
2✔
1575
      }
1576
      applicationEvent = new PayloadApplicationEvent<>(this, event, payloadType);
7✔
1577
    }
1578

1579
    // Determine event type only once (for multicast and parent publish)
1580
    if (eventType == null) {
2✔
1581
      eventType = ResolvableType.forInstance(applicationEvent);
3✔
1582
      if (typeHint == null) {
2✔
1583
        typeHint = eventType;
2✔
1584
      }
1585
    }
1586

1587
    // Multicast right now if possible - or lazily once the multicaster is initialized
1588
    if (this.earlyApplicationEvents != null) {
3✔
1589
      this.earlyApplicationEvents.add(applicationEvent);
6✔
1590
    }
1591
    else if (this.applicationEventMulticaster != null) {
3✔
1592
      this.applicationEventMulticaster.multicastEvent(applicationEvent, eventType);
5✔
1593
    }
1594

1595
    // Publish event via parent context as well...
1596
    if (parent != null) {
3✔
1597
      if (parent instanceof AbstractApplicationContext parentCtx) {
9✔
1598
        parentCtx.publishEvent(event, typeHint);
5✔
1599
      }
1600
      else {
1601
        this.parent.publishEvent(event);
4✔
1602
      }
1603
    }
1604
  }
1✔
1605

1606
  protected void registerApplicationListeners() {
1607
    logger.debug("Registering application-listeners");
4✔
1608

1609
    // Register statically specified listeners first.
1610
    ApplicationEventMulticaster eventMulticaster = getApplicationEventMulticaster();
3✔
1611
    for (ApplicationListener<?> listener : getApplicationListeners()) {
11✔
1612
      eventMulticaster.addApplicationListener(listener);
3✔
1613
    }
1✔
1614

1615
    // Do not initialize FactoryBeans here: We need to leave all regular beans
1616
    // uninitialized to let post-processors apply to them!
1617
    var listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
6✔
1618
    for (String listenerBeanName : listenerBeanNames) {
16✔
1619
      eventMulticaster.addApplicationListenerBean(listenerBeanName);
3✔
1620
    }
1621

1622
    logger.debug("Publish early application events");
4✔
1623
    // Publish early application events now that we finally have a multicaster...
1624
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
3✔
1625
    this.earlyApplicationEvents = null;
3✔
1626
    if (CollectionUtils.isNotEmpty(earlyEventsToProcess)) {
3✔
1627
      for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
10✔
1628
        eventMulticaster.multicastEvent(earlyEvent);
3✔
1629
      }
1✔
1630
    }
1631
  }
1✔
1632

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

1653
  @Override
1654
  public void removeApplicationListener(ApplicationListener<?> listener) {
1655
    Assert.notNull(listener, "ApplicationListener is required");
3✔
1656
    if (applicationEventMulticaster != null) {
3✔
1657
      applicationEventMulticaster.removeApplicationListener(listener);
4✔
1658
    }
1659
    applicationListeners.remove(listener);
5✔
1660
  }
1✔
1661

1662
  /**
1663
   * Finish the initialization of this context's bean factory,
1664
   * initializing all remaining singleton beans.
1665
   */
1666
  protected void finishBeanFactoryInitialization(ConfigurableBeanFactory beanFactory) {
1667
    // Mark current thread for singleton instantiation with applied bootstrap locking.
1668
    beanFactory.prepareSingletonBootstrap();
2✔
1669

1670
    // Initialize bootstrap executor for this context.
1671
    if (beanFactory.containsBean(BOOTSTRAP_EXECUTOR_BEAN_NAME) &&
7✔
1672
            beanFactory.isTypeMatch(BOOTSTRAP_EXECUTOR_BEAN_NAME, Executor.class)) {
2!
1673
      beanFactory.setBootstrapExecutor(
5✔
1674
              beanFactory.getBean(BOOTSTRAP_EXECUTOR_BEAN_NAME, Executor.class));
2✔
1675
    }
1676

1677
    // Initialize conversion service for this context.
1678
    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME)
7✔
1679
            && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
2!
1680
      beanFactory.setConversionService(
5✔
1681
              beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
2✔
1682
    }
1683

1684
    // Register a default embedded value resolver if no BeanFactoryPostProcessor
1685
    // (such as a PropertySourcesPlaceholderConfigurer bean) registered any before:
1686
    // at this point, primarily for resolution in annotation attribute values.
1687
    if (!beanFactory.hasEmbeddedValueResolver()) {
3✔
1688
      beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolveRequiredPlaceholders(strVal));
9✔
1689
    }
1690

1691
    // Call BeanFactoryInitializer beans early to allow for initializing specific other beans early.
1692
    var initializerNames = beanFactory.getBeanNamesForType(BeanFactoryInitializer.class, false, false);
6✔
1693
    for (String initializerName : initializerNames) {
10!
1694
      beanFactory.getBean(initializerName, BeanFactoryInitializer.class).initialize(beanFactory);
×
1695
    }
1696

1697
    // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
1698
    var weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
6✔
1699
    for (String weaverAwareName : weaverAwareNames) {
16✔
1700
      try {
1701
        beanFactory.getBean(weaverAwareName, LoadTimeWeaverAware.class);
5✔
1702
      }
1703
      catch (BeanNotOfRequiredTypeException ex) {
×
1704
        logger.debug("Failed to initialize LoadTimeWeaverAware bean '{}' due to unexpected type mismatch: {}",
×
1705
                weaverAwareName, ex.getMessage());
×
1706
      }
1✔
1707
    }
1708

1709
    // Stop using the temporary ClassLoader for type matching.
1710
    beanFactory.setTempClassLoader(null);
3✔
1711

1712
    // Allow for caching all bean definition metadata, not expecting further changes.
1713
    beanFactory.freezeConfiguration();
2✔
1714

1715
    // Instantiate all remaining (non-lazy-init) singletons.
1716
    beanFactory.preInstantiateSingletons();
2✔
1717
  }
1✔
1718

1719
  /**
1720
   * Finish the refresh of this context, invoking the LifecycleProcessor's
1721
   * onRefresh() method and publishing the {@link ContextRefreshedEvent}.
1722
   */
1723
  protected void finishRefresh() {
1724
    // Reset common introspection caches in core infrastructure.
1725
    resetCommonCaches();
2✔
1726

1727
    // Clear context-level resource caches (such as ASM metadata from scanning).
1728
    clearResourceCaches();
2✔
1729

1730
    // Initialize lifecycle processor for this context.
1731
    initLifecycleProcessor();
2✔
1732

1733
    // Propagate refresh to lifecycle processor first.
1734
    getLifecycleProcessor().onRefresh();
3✔
1735

1736
    // Publish the final event.
1737
    publishEvent(new ContextRefreshedEvent(this));
6✔
1738

1739
    applyState(State.STARTED);
3✔
1740
    Duration duration = Duration.between(getStartupDate(), Instant.now());
5✔
1741
    logger.info("Application context startup in {} ms", duration.toMillis());
7✔
1742
  }
1✔
1743

1744
  @Override
1745
  public void clearResourceCaches() {
1746
    super.clearResourceCaches();
2✔
1747
    if (patternResourceLoader instanceof PathMatchingPatternResourceLoader pmprl) {
9✔
1748
      pmprl.clearCache();
2✔
1749
    }
1750
  }
1✔
1751

1752
  //---------------------------------------------------------------------
1753
  // Abstract methods that must be implemented by subclasses
1754
  //---------------------------------------------------------------------
1755

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

1770
  /**
1771
   * Subclasses must implement this method to release their internal bean factory.
1772
   * This method gets invoked by {@link #close()} after all other shutdown work.
1773
   * <p>Should never throw an exception but rather log shutdown failures.
1774
   *
1775
   * @since 4.0
1776
   */
1777
  protected void closeBeanFactory() {
1778
  }
×
1779

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

1797
  // Object
1798

1799
  /**
1800
   * Return information about this context.
1801
   */
1802
  @Override
1803
  public String toString() {
1804
    return "%s: state: [%s], on startup date: %s, parent: %s".formatted(
8✔
1805
            getDisplayName(), state, startupDate, parent != null ? parent.getDisplayName() : "none");
23✔
1806
  }
1807

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

© 2026 Coveralls, Inc