• 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

57.69
today-context/src/main/java/infra/context/support/AbstractRefreshableApplicationContext.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.List;
24

25
import infra.beans.BeansException;
26
import infra.beans.factory.config.BeanDefinition;
27
import infra.beans.factory.support.BeanDefinitionRegistry;
28
import infra.beans.factory.support.StandardBeanFactory;
29
import infra.context.ApplicationContext;
30
import infra.context.ApplicationContextException;
31

32
/**
33
 * Base class for {@link infra.context.ApplicationContext}
34
 * implementations which are supposed to support multiple calls to {@link #refresh()},
35
 * creating a new internal bean factory instance every time.
36
 * Typically (but not necessarily), such a context will be driven by
37
 * a set of config locations to load bean definitions from.
38
 *
39
 * <p>The only method to be implemented by subclasses is {@link #loadBeanDefinitions},
40
 * which gets invoked on each refresh. A concrete implementation is supposed to load
41
 * bean definitions into the given
42
 * {@link StandardBeanFactory},
43
 * typically delegating to one or more specific bean definition readers.
44
 *
45
 * <p><b>Note that there is a similar base class for WebApplicationContexts.</b>
46
 * {@link infra.web.mock.support.AbstractRefreshableWebApplicationContext}
47
 * provides the same subclassing strategy, but additionally pre-implements
48
 * all context functionality for web environments. There is also a
49
 * pre-defined way to receive config locations for a web context.
50
 *
51
 * @author Juergen Hoeller
52
 * @author Chris Beams
53
 * @author <a href="https://github.com/TAKETODAY">Harry Yang</a>
54
 * @see #loadBeanDefinitions
55
 * @see StandardBeanFactory
56
 * @see infra.web.mock.support.AbstractRefreshableWebApplicationContext
57
 * @since 4.0 2022/2/20 17:36
58
 */
59
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext
60
        implements BeanDefinitionRegistry {
61

62
  @Nullable
63
  private Boolean allowBeanDefinitionOverriding;
64

65
  @Nullable
66
  private Boolean allowCircularReferences;
67

68
  /** Bean factory for this context. */
69
  @Nullable
70
  private volatile StandardBeanFactory beanFactory;
71

72
  /**
73
   * Create a new AbstractRefreshableApplicationContext with no parent.
74
   */
75
  public AbstractRefreshableApplicationContext() { }
3✔
76

77
  /**
78
   * Create a new AbstractRefreshableApplicationContext with the given parent context.
79
   *
80
   * @param parent the parent context
81
   */
82
  public AbstractRefreshableApplicationContext(@Nullable ApplicationContext parent) {
83
    super(parent);
3✔
84
  }
1✔
85

86
  /**
87
   * Set whether it should be allowed to override bean definitions by registering
88
   * a different definition with the same name, automatically replacing the former.
89
   * If not, an exception will be thrown. Default is "true".
90
   *
91
   * @see StandardBeanFactory#setAllowBeanDefinitionOverriding
92
   */
93
  public void setAllowBeanDefinitionOverriding(boolean allowBeanDefinitionOverriding) {
94
    this.allowBeanDefinitionOverriding = allowBeanDefinitionOverriding;
×
95
  }
×
96

97
  /**
98
   * Set whether to allow circular references between beans - and automatically
99
   * try to resolve them.
100
   * <p>Default is "true". Turn this off to throw an exception when encountering
101
   * a circular reference, disallowing them completely.
102
   *
103
   * @see StandardBeanFactory#setAllowCircularReferences
104
   */
105
  public void setAllowCircularReferences(boolean allowCircularReferences) {
106
    this.allowCircularReferences = allowCircularReferences;
×
107
  }
×
108

109
  /**
110
   * This implementation performs an actual refresh of this context's underlying
111
   * bean factory, shutting down the previous bean factory (if any) and
112
   * initializing a fresh bean factory for the next phase of the context's lifecycle.
113
   */
114
  @Override
115
  protected final void refreshBeanFactory() throws BeansException {
116
    if (hasBeanFactory()) {
3✔
117
      destroyBeans();
2✔
118
      closeBeanFactory();
2✔
119
    }
120
    try {
121
      StandardBeanFactory beanFactory = createBeanFactory();
3✔
122
      beanFactory.setSerializationId(getId());
4✔
123
      customizeBeanFactory(beanFactory);
3✔
124
      loadBeanDefinitions(beanFactory);
3✔
125
      this.beanFactory = beanFactory;
3✔
126
    }
127
    catch (IOException ex) {
×
128
      throw new ApplicationContextException(
×
129
              "I/O error parsing bean definition source for " + getDisplayName(), ex);
×
130
    }
1✔
131
  }
1✔
132

133
  @Override
134
  protected void cancelRefresh(Throwable ex) {
135
    StandardBeanFactory beanFactory = this.beanFactory;
3✔
136
    if (beanFactory != null) {
2!
137
      beanFactory.setSerializationId(null);
3✔
138
    }
139
    super.cancelRefresh(ex);
3✔
140
  }
1✔
141

142
  @Override
143
  protected final void closeBeanFactory() {
144
    StandardBeanFactory beanFactory = this.beanFactory;
3✔
145
    if (beanFactory != null) {
2!
146
      beanFactory.setSerializationId(null);
3✔
147
      this.beanFactory = null;
3✔
148
    }
149
    this.setBootstrapContext(null);
3✔
150
  }
1✔
151

152
  /**
153
   * Determine whether this context currently holds a bean factory,
154
   * i.e. has been refreshed at least once and not been closed yet.
155
   */
156
  protected final boolean hasBeanFactory() {
157
    return beanFactory != null;
7✔
158
  }
159

160
  @Override
161
  public final StandardBeanFactory getBeanFactory() {
162
    StandardBeanFactory beanFactory = this.beanFactory;
3✔
163
    if (beanFactory == null) {
2!
164
      throw new IllegalStateException("BeanFactory not initialized or already closed - " +
×
165
              "call 'refresh' before accessing beans via the ApplicationContext");
166
    }
167
    return beanFactory;
2✔
168
  }
169

170
  /**
171
   * Overridden to turn it into a no-op: With AbstractRefreshableApplicationContext,
172
   * {@link #getBeanFactory()} serves a strong assertion for an active context anyway.
173
   */
174
  @Override
175
  protected void assertBeanFactoryActive() { }
1✔
176

177
  /**
178
   * Create an internal bean factory for this context.
179
   * Called for each {@link #refresh()} attempt.
180
   * <p>The default implementation creates a
181
   * {@link StandardBeanFactory}
182
   * with the {@linkplain #getInternalParentBeanFactory() internal bean factory} of this
183
   * context's parent as parent bean factory. Can be overridden in subclasses,
184
   * for example to customize StandardBeanFactory's settings.
185
   *
186
   * @return the bean factory for this context
187
   * @see StandardBeanFactory#setAllowBeanDefinitionOverriding
188
   * @see StandardBeanFactory#setAllowEagerClassLoading
189
   * @see StandardBeanFactory#setAllowCircularReferences
190
   * @see StandardBeanFactory#setAllowRawInjectionDespiteWrapping
191
   */
192
  protected StandardBeanFactory createBeanFactory() {
193
    return new StandardBeanFactory(getInternalParentBeanFactory());
6✔
194
  }
195

196
  /**
197
   * Customize the internal bean factory used by this context.
198
   * Called for each {@link #refresh()} attempt.
199
   * <p>The default implementation applies this context's
200
   * {@linkplain #setAllowBeanDefinitionOverriding "allowBeanDefinitionOverriding"}
201
   * and {@linkplain #setAllowCircularReferences "allowCircularReferences"} settings,
202
   * if specified. Can be overridden in subclasses to customize any of
203
   * {@link StandardBeanFactory}'s settings.
204
   *
205
   * @param beanFactory the newly created bean factory for this context
206
   * @see StandardBeanFactory#setAllowBeanDefinitionOverriding
207
   * @see StandardBeanFactory#setAllowCircularReferences
208
   * @see StandardBeanFactory#setAllowRawInjectionDespiteWrapping
209
   * @see StandardBeanFactory#setAllowEagerClassLoading
210
   */
211
  protected void customizeBeanFactory(StandardBeanFactory beanFactory) {
212
    if (this.allowBeanDefinitionOverriding != null) {
3!
213
      beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
×
214
    }
215
    if (this.allowCircularReferences != null) {
3!
216
      beanFactory.setAllowCircularReferences(this.allowCircularReferences);
×
217
    }
218
  }
1✔
219

220
  /**
221
   * Load bean definitions into the given bean factory, typically through
222
   * delegating to one or more bean definition readers.
223
   *
224
   * @param beanFactory the bean factory to load bean definitions into
225
   * @throws BeansException if parsing of the bean definitions failed
226
   * @throws IOException if loading of bean definition files failed
227
   */
228
  protected abstract void loadBeanDefinitions(StandardBeanFactory beanFactory)
229
          throws BeansException, IOException;
230

231
  //---------------------------------------------------------------------
232
  // Implementation of BeanDefinitionRegistry interface
233
  //---------------------------------------------------------------------
234

235
  @Override
236
  public void registerBeanDefinition(String beanName, BeanDefinition def) {
237
    getBeanFactory().registerBeanDefinition(beanName, def);
5✔
238
  }
1✔
239

240
  @Override
241
  public void removeBeanDefinition(String beanName) {
242
    getBeanFactory().removeBeanDefinition(beanName);
×
243
  }
×
244

245
  @Override
246
  public BeanDefinition getBeanDefinition(String beanName) {
247
    return getBeanFactory().getBeanDefinition(beanName);
×
248
  }
249

250
  @Nullable
251
  @Override
252
  public BeanDefinition getBeanDefinition(Class<?> requiredType) {
253
    return getBeanFactory().getBeanDefinition(requiredType);
×
254
  }
255

256
  @Override
257
  public boolean containsBeanDefinition(Class<?> type) {
258
    return getBeanFactory().containsBeanDefinition(type);
×
259
  }
260

261
  @Override
262
  public boolean containsBeanDefinition(Class<?> type, boolean equals) {
263
    return getBeanFactory().containsBeanDefinition(type, equals);
×
264
  }
265

266
  @Override
267
  public boolean containsBeanDefinition(String beanName, Class<?> type) {
268
    return getBeanFactory().containsBeanDefinition(beanName, type);
×
269
  }
270

271
  @Override
272
  public boolean containsBeanDefinition(String beanName) {
273
    return getBeanFactory().containsBeanDefinition(beanName);
5✔
274
  }
275

276
  @Override
277
  public String[] getBeanDefinitionNames() {
278
    return getBeanFactory().getBeanDefinitionNames();
×
279
  }
280

281
  @Override
282
  public int getBeanDefinitionCount() {
283
    return getBeanFactory().getBeanDefinitionCount();
×
284
  }
285

286
  @Override
287
  public boolean isAllowBeanDefinitionOverriding() {
288
    return getBeanFactory().isAllowBeanDefinitionOverriding();
×
289
  }
290

291
  @Override
292
  public boolean isBeanDefinitionOverridable(String beanName) {
293
    return getBeanFactory().isBeanDefinitionOverridable(beanName);
×
294
  }
295

296
  @Override
297
  public void registerAlias(String name, String alias) {
298
    getBeanFactory().registerAlias(name, alias);
×
299
  }
×
300

301
  @Override
302
  public void removeAlias(String alias) {
303
    getBeanFactory().removeAlias(alias);
×
304
  }
×
305

306
  @Override
307
  public boolean isAlias(String name) {
308
    return getBeanFactory().isAlias(name);
×
309
  }
310

311
  @Override
312
  public List<String> getAliasList(String name) {
313
    return getBeanFactory().getAliasList(name);
×
314
  }
315

316
  @Override
317
  public boolean isBeanNameInUse(String beanName) {
318
    return getBeanFactory().isBeanNameInUse(beanName);
×
319
  }
320

321
}
322

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