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

TAKETODAY / today-infrastructure / 18154768944

01 Oct 2025 07:26AM UTC coverage: 81.882% (-0.005%) from 81.887%
18154768944

push

github

web-flow
Merge pull request #290 from TAKETODAY/dev/jspecify

jspecify

59788 of 78013 branches covered (76.64%)

Branch coverage included in aggregate %.

141239 of 167496 relevant lines covered (84.32%)

3.6 hits per line

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

91.12
today-context/src/main/java/infra/context/support/GenericApplicationContext.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.util.ArrayList;
24
import java.util.Collection;
25
import java.util.List;
26
import java.util.Set;
27
import java.util.concurrent.atomic.AtomicBoolean;
28
import java.util.function.Supplier;
29

30
import infra.aot.hint.RuntimeHints;
31
import infra.aot.hint.support.ClassHintUtils;
32
import infra.beans.BeansException;
33
import infra.beans.PropertyValues;
34
import infra.beans.factory.BeanFactory;
35
import infra.beans.factory.BeanRegistrar;
36
import infra.beans.factory.config.AutowireCapableBeanFactory;
37
import infra.beans.factory.config.BeanDefinition;
38
import infra.beans.factory.config.BeanDefinitionCustomizer;
39
import infra.beans.factory.config.BeanFactoryPostProcessor;
40
import infra.beans.factory.config.ConfigurableBeanFactory;
41
import infra.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
42
import infra.beans.factory.support.BeanDefinitionRegistry;
43
import infra.beans.factory.support.BeanDefinitionRegistryPostProcessor;
44
import infra.beans.factory.support.BeanRegistryAdapter;
45
import infra.beans.factory.support.MergedBeanDefinitionPostProcessor;
46
import infra.beans.factory.support.RootBeanDefinition;
47
import infra.beans.factory.support.StandardBeanFactory;
48
import infra.context.ApplicationContext;
49
import infra.context.ApplicationContextAware;
50
import infra.core.io.DefaultResourceLoader;
51
import infra.core.io.PatternResourceLoader;
52
import infra.core.io.ProtocolResolver;
53
import infra.core.io.Resource;
54
import infra.core.io.ResourceConsumer;
55
import infra.core.io.ResourceLoader;
56
import infra.lang.Assert;
57
import infra.util.CollectionUtils;
58

59
/**
60
 * Generic ApplicationContext implementation that holds a single internal
61
 * {@link StandardBeanFactory}
62
 * instance and does not assume a specific bean definition format. Implements
63
 * the {@link BeanDefinitionRegistry}
64
 * interface in order to allow for applying any bean definition readers to it.
65
 *
66
 * <p>Typical usage is to register a variety of bean definitions via the
67
 * {@link BeanDefinitionRegistry}
68
 * interface and then call {@link #refresh()} to initialize those beans
69
 * with application context semantics (handling
70
 * {@link ApplicationContextAware}, auto-detecting
71
 * {@link BeanFactoryPostProcessor BeanFactoryPostProcessors},
72
 * etc).
73
 *
74
 * <p>In contrast to other ApplicationContext implementations that create a new
75
 * internal BeanFactory instance for each refresh, the internal BeanFactory of
76
 * this context is available right from the start, to be able to register bean
77
 * definitions on it. {@link #refresh()} may only be called once.
78
 *
79
 * <p>Usage example:
80
 *
81
 * <pre class="code">
82
 * GenericApplicationContext ctx = new GenericApplicationContext();
83
 * XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx);
84
 * xmlReader.loadBeanDefinitions(new ClassPathResource("applicationContext.xml"));
85
 * PropertiesBeanDefinitionReader propReader = new PropertiesBeanDefinitionReader(ctx);
86
 * propReader.loadBeanDefinitions(new ClassPathResource("otherBeans.properties"));
87
 * ctx.refresh();
88
 *
89
 * MyBean myBean = (MyBean) ctx.getBean("myBean");
90
 * ...</pre>
91
 *
92
 * <p>For custom application context implementations that are supposed to read
93
 * special bean definition formats in a refreshable manner, consider deriving
94
 * from the {@link AbstractRefreshableApplicationContext} base class.
95
 *
96
 * @author Juergen Hoeller
97
 * @author Chris Beams
98
 * @author <a href="https://github.com/TAKETODAY">Harry Yang</a>
99
 * @author TODAY 2021/10/1 16:25
100
 * @see #registerBeanDefinition
101
 * @see #refresh()
102
 * @since 4.0
103
 */
104
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
105

106
  protected final StandardBeanFactory beanFactory;
107

108
  @Nullable
109
  private ResourceLoader resourceLoader;
110

111
  private boolean customClassLoader = false;
6✔
112

113
  private final AtomicBoolean refreshed = new AtomicBoolean();
10✔
114

115
  /**
116
   * Create a new GenericApplicationContext.
117
   *
118
   * @see #registerBeanDefinition
119
   * @see #refresh
120
   */
121
  public GenericApplicationContext() {
2✔
122
    this.beanFactory = new StandardBeanFactory();
5✔
123
  }
1✔
124

125
  /**
126
   * Create a new GenericApplicationContext with the given StandardBeanFactory.
127
   *
128
   * @param beanFactory the StandardBeanFactory instance to use for this context
129
   * @see #registerBeanDefinition
130
   * @see #refresh
131
   */
132
  public GenericApplicationContext(StandardBeanFactory beanFactory) {
2✔
133
    Assert.notNull(beanFactory, "BeanFactory is required");
3✔
134
    this.beanFactory = beanFactory;
3✔
135
  }
1✔
136

137
  /**
138
   * Create a new GenericApplicationContext with the given parent.
139
   *
140
   * @param parent the parent application context
141
   * @see #registerBeanDefinition
142
   * @see #refresh
143
   */
144
  public GenericApplicationContext(@Nullable ApplicationContext parent) {
145
    this();
2✔
146
    setParent(parent);
3✔
147
  }
1✔
148

149
  /**
150
   * Create a new GenericApplicationContext with the given StandardBeanFactory.
151
   *
152
   * @param beanFactory the StandardBeanFactory instance to use for this context
153
   * @param parent the parent application context
154
   * @see #registerBeanDefinition
155
   * @see #refresh
156
   */
157
  public GenericApplicationContext(StandardBeanFactory beanFactory, ApplicationContext parent) {
158
    this(beanFactory);
×
159
    setParent(parent);
×
160
  }
×
161

162
  /**
163
   * Set the parent of this application context, also setting
164
   * the parent of the internal BeanFactory accordingly.
165
   *
166
   * @see ConfigurableBeanFactory#setParentBeanFactory
167
   */
168
  @Override
169
  public void setParent(@Nullable ApplicationContext parent) {
170
    super.setParent(parent);
3✔
171
    this.beanFactory.setParentBeanFactory(getInternalParentBeanFactory());
5✔
172
  }
1✔
173

174
  /**
175
   * Do nothing: We hold a single internal BeanFactory and rely on callers
176
   * to register beans through our public methods (or the BeanFactory's).
177
   *
178
   * @see #registerBeanDefinition
179
   */
180
  @Override
181
  protected final void refreshBeanFactory() throws IllegalStateException {
182
    if (!this.refreshed.compareAndSet(false, true)) {
6✔
183
      throw new IllegalStateException(
5✔
184
              "GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
185
    }
186
    this.beanFactory.setSerializationId(getId());
5✔
187
  }
1✔
188

189
  @Override
190
  protected void cancelRefresh(Throwable ex) {
191
    this.beanFactory.setSerializationId(null);
4✔
192
    super.cancelRefresh(ex);
3✔
193
  }
1✔
194

195
  /**
196
   * Not much to do: We hold a single internal BeanFactory that will never
197
   * get released.
198
   */
199
  @Override
200
  protected final void closeBeanFactory() {
201
    this.beanFactory.setSerializationId(null);
4✔
202
  }
1✔
203

204
  /**
205
   * Return the underlying bean factory of this context,
206
   * available for registering bean definitions.
207
   * <p><b>NOTE:</b> You need to call {@link #refresh()} to initialize the
208
   * bean factory and its contained beans with application context semantics
209
   * (autodetecting BeanFactoryPostProcessors, etc).
210
   *
211
   * @return the internal bean factory (as StandardBeanFactory)
212
   */
213
  @Override
214
  public StandardBeanFactory getBeanFactory() {
215
    return beanFactory;
3✔
216
  }
217

218
  @Override
219
  public AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException {
220
    assertBeanFactoryActive();
2✔
221
    return this.beanFactory;
3✔
222
  }
223

224
  /**
225
   * Set a ResourceLoader to use for this context. If set, the context will
226
   * delegate all {@code getResource} calls to the given ResourceLoader.
227
   * If not set, default resource loading will apply.
228
   * <p>The main reason to specify a custom ResourceLoader is to resolve
229
   * resource paths (without URL prefix) in a specific fashion.
230
   * The default behavior is to resolve such paths as class path locations.
231
   * To resolve resource paths as file system locations, specify a
232
   * FileSystemResourceLoader here.
233
   * <p>You can also pass in a full PatternResourceLoader, which will
234
   * be autodetected by the context and used for {@code getResources}
235
   * calls as well. Else, default resource pattern matching will apply.
236
   *
237
   * @see #getResource
238
   * @see DefaultResourceLoader
239
   * @see PatternResourceLoader
240
   * @see #getResourcesArray
241
   */
242
  public void setResourceLoader(@Nullable ResourceLoader resourceLoader) {
243
    this.resourceLoader = resourceLoader;
3✔
244
  }
1✔
245

246
  //---------------------------------------------------------------------
247
  // ResourceLoader / PatternResourceLoader override if necessary
248
  //---------------------------------------------------------------------
249

250
  /**
251
   * This implementation delegates to this context's {@code ResourceLoader} if set,
252
   * falling back to the default superclass behavior otherwise.
253
   * <p>This method also honors registered
254
   * {@linkplain #getProtocolResolvers() protocol resolvers} when a custom
255
   * {@code ResourceLoader} has been set.
256
   *
257
   * @see #setResourceLoader(ResourceLoader)
258
   * @see #addProtocolResolver(ProtocolResolver)
259
   */
260
  @Override
261
  public Resource getResource(String location) {
262
    if (this.resourceLoader != null) {
3✔
263
      Collection<ProtocolResolver> protocolResolvers = getProtocolResolvers();
3✔
264
      if (CollectionUtils.isNotEmpty(protocolResolvers)) {
3✔
265
        for (ProtocolResolver protocolResolver : protocolResolvers) {
10✔
266
          Resource resource = protocolResolver.resolve(location, this);
5✔
267
          if (resource != null) {
2✔
268
            return resource;
2✔
269
          }
270
        }
1✔
271
      }
272
      return this.resourceLoader.getResource(location);
5✔
273
    }
274
    return super.getResource(location);
4✔
275
  }
276

277
  /**
278
   * This implementation delegates to this context's ResourceLoader if it
279
   * implements the PatternResourceLoader interface, falling back to the
280
   * default superclass behavior else.
281
   *
282
   * @see #setResourceLoader
283
   */
284
  @Override
285
  public Set<Resource> getResources(String locationPattern) throws IOException {
286
    if (resourceLoader instanceof PatternResourceLoader loader) {
6!
287
      return loader.getResources(locationPattern);
×
288
    }
289
    return super.getResources(locationPattern);
4✔
290
  }
291

292
  /**
293
   * This implementation delegates to this context's ResourceLoader if it
294
   * implements the PatternResourceLoader interface, falling back to the
295
   * default superclass behavior else.
296
   *
297
   * @see #setResourceLoader
298
   */
299
  @Override
300
  public void scan(String locationPattern, ResourceConsumer consumer) throws IOException {
301
    if (resourceLoader instanceof PatternResourceLoader loader) {
6!
302
      loader.scan(locationPattern, consumer);
×
303
    }
304
    else {
305
      super.scan(locationPattern, consumer);
4✔
306
    }
307
  }
1✔
308

309
  @Override
310
  public void setClassLoader(@Nullable ClassLoader classLoader) {
311
    super.setClassLoader(classLoader);
3✔
312
    this.customClassLoader = true;
3✔
313
  }
1✔
314

315
  @Override
316
  @Nullable
317
  public ClassLoader getClassLoader() {
318
    if (this.resourceLoader != null && !this.customClassLoader) {
6✔
319
      return this.resourceLoader.getClassLoader();
4✔
320
    }
321
    return super.getClassLoader();
3✔
322
  }
323

324
  //---------------------------------------------------------------------
325
  // Implementation of BeanDefinitionRegistry
326
  //---------------------------------------------------------------------
327

328
  @Override
329
  public void registerBeanDefinition(String name, BeanDefinition def) {
330
    beanFactory.registerBeanDefinition(name, def);
5✔
331
  }
1✔
332

333
  @Override
334
  public void removeBeanDefinition(String beanName) {
335
    beanFactory.removeBeanDefinition(beanName);
4✔
336
  }
1✔
337

338
  @Nullable
339
  @Override
340
  public BeanDefinition getBeanDefinition(Class<?> beanClass) {
341
    return beanFactory.getBeanDefinition(beanClass);
5✔
342
  }
343

344
  @Override
345
  public boolean containsBeanDefinition(Class<?> type) {
346
    return beanFactory.containsBeanDefinition(type);
5✔
347
  }
348

349
  @Override
350
  public boolean containsBeanDefinition(Class<?> type, boolean equals) {
351
    return beanFactory.containsBeanDefinition(type, equals);
×
352
  }
353

354
  @Override
355
  public boolean isBeanNameInUse(String beanName) {
356
    return beanFactory.isBeanNameInUse(beanName);
5✔
357
  }
358

359
  @Override
360
  public boolean isAllowBeanDefinitionOverriding() {
361
    return beanFactory.isAllowBeanDefinitionOverriding();
×
362
  }
363

364
  @Override
365
  public boolean isBeanDefinitionOverridable(String beanName) {
366
    return beanFactory.isBeanDefinitionOverridable(beanName);
5✔
367
  }
368

369
  @Override
370
  public int getBeanDefinitionCount() {
371
    return beanFactory.getBeanDefinitionCount();
4✔
372
  }
373

374
  @Override
375
  public String[] getBeanDefinitionNames() {
376
    return beanFactory.getBeanDefinitionNames();
4✔
377
  }
378

379
  @Override
380
  public boolean containsBeanDefinition(String beanName) {
381
    return beanFactory.containsBeanDefinition(beanName);
5✔
382
  }
383

384
  @Override
385
  public BeanDefinition getBeanDefinition(String beanName) {
386
    return beanFactory.getBeanDefinition(beanName);
5✔
387
  }
388

389
  //---------------------------------------------------------------------
390
  // AOT processing
391
  //---------------------------------------------------------------------
392

393
  /**
394
   * Load or refresh the persistent representation of the configuration up to
395
   * a point where the underlying bean factory is ready to create bean
396
   * instances.
397
   * <p>This variant of {@link #refresh()} is used by Ahead of Time (AOT)
398
   * processing that optimizes the application context, typically at build time.
399
   * <p>In this mode, only {@link BeanDefinitionRegistryPostProcessor} and
400
   * {@link MergedBeanDefinitionPostProcessor} are invoked.
401
   *
402
   * @param runtimeHints the runtime hints
403
   * @throws BeansException if the bean factory could not be initialized
404
   * @throws IllegalStateException if already initialized and multiple refresh
405
   * attempts are not supported
406
   */
407
  public void refreshForAotProcessing(RuntimeHints runtimeHints) {
408
    if (logger.isDebugEnabled()) {
4!
409
      logger.debug("Preparing bean factory for AOT processing");
×
410
    }
411
    prepareRefresh();
2✔
412
    obtainFreshBeanFactory();
3✔
413
    registerFrameworkComponents(beanFactory);
4✔
414
    prepareBeanFactory(beanFactory);
4✔
415
    postProcessBeanFactory(beanFactory);
4✔
416
    invokeBeanFactoryPostProcessors(beanFactory);
4✔
417
    beanFactory.freezeConfiguration();
3✔
418
    PostProcessorRegistrationDelegate.invokeMergedBeanDefinitionPostProcessors(beanFactory);
3✔
419
    preDetermineBeanTypes(runtimeHints);
3✔
420
  }
1✔
421

422
  /**
423
   * Pre-determine bean types in order to trigger early proxy class creation.
424
   *
425
   * @see BeanFactory#getType
426
   * @see SmartInstantiationAwareBeanPostProcessor#determineBeanType
427
   */
428
  private void preDetermineBeanTypes(RuntimeHints runtimeHints) {
429
    ArrayList<String> singletons = new ArrayList<>();
4✔
430
    ArrayList<String> lazyBeans = new ArrayList<>();
4✔
431

432
    // First round: pre-registered singleton instances, if any.
433
    for (String beanName : this.beanFactory.getSingletonNames()) {
18✔
434
      Class<?> beanType = this.beanFactory.getType(beanName);
5✔
435
      if (beanType != null) {
2!
436
        ClassHintUtils.registerProxyIfNecessary(beanType, runtimeHints);
3✔
437
      }
438
      singletons.add(beanName);
4✔
439
    }
440

441
    List<SmartInstantiationAwareBeanPostProcessor> bpps =
3✔
442
            PostProcessorRegistrationDelegate.loadBeanPostProcessors(
2✔
443
                    beanFactory, SmartInstantiationAwareBeanPostProcessor.class);
444

445
    // Second round: non-lazy singleton beans in definition order,
446
    // matching preInstantiateSingletons.
447
    for (String beanName : this.beanFactory.getBeanDefinitionNames()) {
18✔
448
      if (!singletons.contains(beanName)) {
4✔
449
        BeanDefinition bd = getBeanDefinition(beanName);
4✔
450
        if (bd.isSingleton() && !bd.isLazyInit()) {
6!
451
          preDetermineBeanType(beanName, bpps, runtimeHints);
6✔
452
        }
453
        else {
454
          lazyBeans.add(beanName);
4✔
455
        }
456
      }
457
    }
458

459
    // Third round: lazy singleton beans and scoped beans.
460
    for (String beanName : lazyBeans) {
10✔
461
      preDetermineBeanType(beanName, bpps, runtimeHints);
5✔
462
    }
1✔
463
  }
1✔
464

465
  private void preDetermineBeanType(String beanName, List<SmartInstantiationAwareBeanPostProcessor> bpps, RuntimeHints runtimeHints) {
466
    Class<?> beanType = this.beanFactory.getType(beanName);
5✔
467
    if (beanType != null) {
2✔
468
      ClassHintUtils.registerProxyIfNecessary(beanType, runtimeHints);
3✔
469
      for (SmartInstantiationAwareBeanPostProcessor bpp : bpps) {
10✔
470
        Class<?> newBeanType = bpp.determineBeanType(beanType, beanName);
5✔
471
        if (newBeanType != beanType) {
3✔
472
          ClassHintUtils.registerProxyIfNecessary(newBeanType, runtimeHints);
3✔
473
          beanType = newBeanType;
2✔
474
        }
475
      }
1✔
476
    }
477
  }
1✔
478

479
  //---------------------------------------------------------------------
480
  // Convenient methods for registering individual beans
481
  //---------------------------------------------------------------------
482

483
  /**
484
   * Register a bean with the given name and bean instance
485
   *
486
   * @param name bean name (must not be null)
487
   * @param obj bean instance (must not be null)
488
   */
489
  public void registerSingleton(String name, Object obj) {
490
    getBeanFactory().registerSingleton(name, obj);
5✔
491
  }
1✔
492

493
  /**
494
   * Register a singleton bean with the underlying bean factory.
495
   * <p>For more advanced needs, register with the underlying BeanFactory directly.
496
   *
497
   * @see #getBeanFactory
498
   */
499
  public void registerSingleton(String name, Class<?> clazz) throws BeansException {
500
    BeanDefinition bd = new RootBeanDefinition(clazz);
5✔
501
    getBeanFactory().registerBeanDefinition(name, bd);
5✔
502
  }
1✔
503

504
  /**
505
   * Register a singleton bean with the underlying bean factory.
506
   * <p>For more advanced needs, register with the underlying BeanFactory directly.
507
   *
508
   * @see #getBeanFactory()
509
   */
510
  public void registerSingleton(String name, Class<?> clazz, @Nullable PropertyValues pvs) throws BeansException {
511
    RootBeanDefinition bd = new RootBeanDefinition(clazz);
5✔
512
    bd.setPropertyValues(pvs);
3✔
513
    getBeanFactory().registerBeanDefinition(name, bd);
5✔
514
  }
1✔
515

516
  /**
517
   * Register a prototype bean with the underlying bean factory.
518
   * <p>For more advanced needs, register with the underlying BeanFactory directly.
519
   *
520
   * @see #getBeanFactory
521
   */
522
  public void registerPrototype(String name, Class<?> clazz) throws BeansException {
523
    RootBeanDefinition bd = new RootBeanDefinition(clazz);
5✔
524
    bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
3✔
525
    getBeanFactory().registerBeanDefinition(name, bd);
5✔
526
  }
1✔
527

528
  /**
529
   * Register a prototype bean with the underlying bean factory.
530
   * <p>For more advanced needs, register with the underlying BeanFactory directly.
531
   *
532
   * @see #getBeanFactory
533
   */
534
  public void registerPrototype(String name, Class<?> clazz, PropertyValues pvs) throws BeansException {
535
    RootBeanDefinition bd = new RootBeanDefinition(clazz);
5✔
536
    bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
3✔
537
    bd.setPropertyValues(pvs);
3✔
538
    getBeanFactory().registerBeanDefinition(name, bd);
5✔
539
  }
1✔
540

541
  public void registerSingleton(Object obj) {
542
    getBeanFactory().registerSingleton(obj);
4✔
543
  }
1✔
544

545
  /**
546
   * Register a bean from the given bean class, optionally providing explicit
547
   * constructor arguments for consideration in the autowiring process.
548
   *
549
   * @param beanClass the class of the bean
550
   * @param constructorArgs custom argument values to be fed into Framework's
551
   * constructor resolution algorithm, resolving either all arguments or just
552
   * specific ones, with the rest to be resolved through regular autowiring
553
   * (may be {@code null} or empty)
554
   */
555
  public <T> void registerBean(Class<T> beanClass, Object... constructorArgs) {
556
    registerBean(null, beanClass, constructorArgs);
5✔
557
  }
1✔
558

559
  /**
560
   * Register a bean from the given bean class, optionally providing explicit
561
   * constructor arguments for consideration in the autowiring process.
562
   *
563
   * @param beanName the name of the bean (may be {@code null})
564
   * @param beanClass the class of the bean
565
   * @param constructorArgs custom argument values to be fed into Framework's
566
   * constructor resolution algorithm, resolving either all arguments or just
567
   * specific ones, with the rest to be resolved through regular autowiring
568
   * (may be {@code null} or empty)
569
   */
570
  public <T> void registerBean(@Nullable String beanName, Class<T> beanClass, Object... constructorArgs) {
571
    registerBean(beanName, beanClass, (Supplier<T>) null,
13✔
572
            bd -> {
573
              for (Object arg : constructorArgs) {
16✔
574
                bd.getConstructorArgumentValues().addGenericArgumentValue(arg);
4✔
575
              }
576
            });
1✔
577
  }
1✔
578

579
  /**
580
   * Register a bean from the given bean class, optionally customizing its
581
   * bean definition metadata (typically declared as a lambda expression).
582
   *
583
   * @param beanClass the class of the bean (resolving a public constructor
584
   * to be autowired, possibly simply the default constructor)
585
   * @param customizers one or more callbacks for customizing the factory's
586
   * {@link BeanDefinition}, e.g. setting a lazy-init or primary flag
587
   * @see #registerBean(String, Class, Supplier, BeanDefinitionCustomizer...)
588
   */
589
  public final <T> void registerBean(Class<T> beanClass, BeanDefinitionCustomizer... customizers) {
590
    registerBean(null, beanClass, null, customizers);
6✔
591
  }
1✔
592

593
  /**
594
   * Register a bean from the given bean class, optionally customizing its
595
   * bean definition metadata (typically declared as a lambda expression).
596
   *
597
   * @param beanName the name of the bean (may be {@code null})
598
   * @param beanClass the class of the bean (resolving a public constructor
599
   * to be autowired, possibly simply the default constructor)
600
   * @param customizers one or more callbacks for customizing the factory's
601
   * {@link BeanDefinition}, e.g. setting a lazy-init or primary flag
602
   * @see #registerBean(String, Class, Supplier, BeanDefinitionCustomizer...)
603
   */
604
  public final <T> void registerBean(@Nullable String beanName, Class<T> beanClass, BeanDefinitionCustomizer... customizers) {
605
    registerBean(beanName, beanClass, null, customizers);
6✔
606
  }
1✔
607

608
  /**
609
   * Register a bean from the given bean class, using the given supplier for
610
   * obtaining a new instance (typically declared as a lambda expression or
611
   * method reference), optionally customizing its bean definition metadata
612
   * (again typically declared as a lambda expression).
613
   *
614
   * @param beanClass the class of the bean
615
   * @param supplier a callback for creating an instance of the bean
616
   * @param customizers one or more callbacks for customizing the factory's
617
   * {@link BeanDefinition}, e.g. setting a lazy-init or primary flag
618
   * @see #registerBean(String, Class, Supplier, BeanDefinitionCustomizer...)
619
   */
620
  public final <T> void registerBean(Class<T> beanClass, Supplier<T> supplier, BeanDefinitionCustomizer... customizers) {
621
    registerBean(null, beanClass, supplier, customizers);
6✔
622
  }
1✔
623

624
  /**
625
   * Register a bean from the given bean class, using the given supplier for
626
   * obtaining a new instance (typically declared as a lambda expression or
627
   * method reference), optionally customizing its bean definition metadata
628
   * (again typically declared as a lambda expression).
629
   * <p>This method can be overridden to adapt the registration mechanism for
630
   * all {@code registerBean} methods (since they all delegate to this one).
631
   *
632
   * @param beanName the name of the bean (may be {@code null})
633
   * @param beanClass the class of the bean
634
   * @param supplier a callback for creating an instance of the bean (in case
635
   * of {@code null}, resolving a public constructor to be autowired instead)
636
   * @param customizers one or more callbacks for customizing the factory's
637
   * {@link BeanDefinition}, e.g. setting a lazy-init or primary flag
638
   */
639
  public <T> void registerBean(@Nullable String beanName, Class<T> beanClass,
640
          @Nullable Supplier<T> supplier, BeanDefinitionCustomizer... customizers) {
641

642
    RootBeanDefinition beanDefinition = new RootBeanDefinition(beanClass);
5✔
643
    if (supplier != null) {
2✔
644
      beanDefinition.setInstanceSupplier(supplier);
3✔
645
    }
646

647
    for (BeanDefinitionCustomizer customizer : customizers) {
16✔
648
      customizer.customize(beanDefinition);
3✔
649
    }
650

651
    String nameToUse = beanName != null ? beanName : beanClass.getName();
7✔
652
    registerBeanDefinition(nameToUse, beanDefinition);
4✔
653
  }
1✔
654

655
  //---------------------------------------------------------------------
656
  // Implementation of AliasRegistry Interface
657
  //---------------------------------------------------------------------
658

659
  @Override
660
  public void registerAlias(String name, String alias) {
661
    beanFactory.registerAlias(name, alias);
5✔
662
  }
1✔
663

664
  @Override
665
  public void removeAlias(String alias) {
666
    beanFactory.removeAlias(alias);
×
667
  }
×
668

669
  @Override
670
  public boolean isAlias(String name) {
671
    return beanFactory.isAlias(name);
×
672
  }
673

674
  @Override
675
  public List<String> getAliasList(String name) {
676
    return beanFactory.getAliasList(name);
×
677
  }
678

679
  /**
680
   * Set whether it should be allowed to override bean definitions by registering
681
   * a different definition with the same name, automatically replacing the former.
682
   * If not, an exception will be thrown. This also applies to overriding aliases.
683
   * <p>Default is "true".
684
   *
685
   * @see #registerBeanDefinition
686
   * @since 4.0
687
   */
688
  public void setAllowBeanDefinitionOverriding(boolean allowBeanDefinitionOverriding) {
689
    this.beanFactory.setAllowBeanDefinitionOverriding(allowBeanDefinitionOverriding);
4✔
690
  }
1✔
691

692
  /**
693
   * Set whether to allow circular references between beans - and automatically
694
   * try to resolve them.
695
   * <p>Default is "true". Turn this off to throw an exception when encountering
696
   * a circular reference, disallowing them completely.
697
   *
698
   * @since 4.0
699
   */
700
  public void setAllowCircularReferences(boolean allowCircularReferences) {
701
    this.beanFactory.setAllowCircularReferences(allowCircularReferences);
×
702
  }
×
703

704
  /**
705
   * Invoke the given registrars for registering their beans with this
706
   * application context.
707
   * <p>This can be used to apply encapsulated pieces of programmatic
708
   * bean registration to this application context without relying on
709
   * individual calls to its context-level {@code registerBean} methods.
710
   *
711
   * @param registrars one or more {@link BeanRegistrar} instances
712
   * @since 5.0
713
   */
714
  public void register(BeanRegistrar... registrars) {
715
    for (BeanRegistrar registrar : registrars) {
16✔
716
      new BeanRegistryAdapter(this.beanFactory, getEnvironment(), registrar.getClass()).register(registrar);
11✔
717
    }
718
  }
1✔
719

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