• 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

66.67
today-context/src/main/java/infra/context/support/SimpleThreadScope.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.util.HashMap;
23
import java.util.Map;
24
import java.util.function.Supplier;
25

26
import infra.beans.factory.config.ConfigurableBeanFactory;
27
import infra.beans.factory.config.CustomScopeConfigurer;
28
import infra.beans.factory.config.Scope;
29
import infra.core.NamedThreadLocal;
30
import infra.logging.Logger;
31
import infra.logging.LoggerFactory;
32

33
/**
34
 * A simple thread-backed {@link Scope} implementation.
35
 *
36
 * <p><b>NOTE:</b> This thread scope is not registered by default in common contexts.
37
 * Instead, you need to explicitly assign it to a scope key in your setup, either through
38
 * {@link ConfigurableBeanFactory#registerScope}
39
 * or through a {@link CustomScopeConfigurer} bean.
40
 *
41
 * <p>{@code SimpleThreadScope} <em>does not clean up any objects</em> associated with it.
42
 * It is therefore typically preferable to use a request-bound scope implementation such
43
 * as {@code infra.web.context.request.RequestScope} in web environments,
44
 * implementing the full lifecycle for scoped attributes (including reliable destruction).
45
 *
46
 * <p>For an implementation of a thread-based {@code Scope} with support for destruction
47
 * callbacks, refer to
48
 * <a href="https://www.springbyexample.org/examples/custom-thread-scope-module.html">Spring by Example</a>.
49
 *
50
 * <p>Thanks to Eugene Kuleshov for submitting the original prototype for a thread scope!
51
 *
52
 * @author Arjen Poutsma
53
 * @author Juergen Hoeller
54
 * @author <a href="https://github.com/TAKETODAY">Harry Yang</a>
55
 * @since 2.1.7 2020-04-02 21:09
56
 */
57
public class SimpleThreadScope implements Scope {
2✔
58
  private static final Logger logger = LoggerFactory.getLogger(SimpleThreadScope.class);
4✔
59

60
  private final ThreadLocal<Map<String, Object>> threadScope =
4✔
61
          NamedThreadLocal.withInitial("SimpleThreadScope", HashMap::new);
2✔
62

63
  @Override
64
  public Object remove(String name) {
65
    Map<String, Object> scope = this.threadScope.get();
×
66
    return scope.remove(name);
×
67
  }
68

69
  @Override
70
  public void registerDestructionCallback(String name, Runnable callback) {
71
    logger.warn("SimpleThreadScope does not support destruction callbacks. " +
×
72
            "Consider using RequestScope in a web environment.");
73
  }
×
74

75
  @Override
76
  public Object get(final String beanName, final Supplier<?> objectFactory) {
77
    Map<String, Object> scope = this.threadScope.get();
5✔
78
    Object scopedObject = scope.get(beanName);
4✔
79
    if (scopedObject == null) {
2✔
80
      scopedObject = objectFactory.get();
3✔
81
      scope.put(beanName, scopedObject);
5✔
82
    }
83
    return scopedObject;
2✔
84
  }
85

86
  @Override
87
  @Nullable
88
  public Object resolveContextualObject(String key) {
89
    return null;
×
90
  }
91

92
  @Override
93
  public String getConversationId() {
94
    return Thread.currentThread().getName();
×
95
  }
96

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