From e1d0176faa5d413d9a4ad8d3c75198b7062f86ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=85=B6=E8=8B=97?= Date: Mon, 16 Mar 2020 13:48:52 +0800 Subject: [PATCH] Add factory to create a NamedThreadLocal with an initial value See gh-24705 --- .../context/support/SimpleThreadScope.java | 9 +--- .../core/NamedThreadLocal.java | 41 ++++++++++++++++++- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/spring-context/src/main/java/org/springframework/context/support/SimpleThreadScope.java b/spring-context/src/main/java/org/springframework/context/support/SimpleThreadScope.java index 0b237eb0b1c..7063bca8745 100644 --- a/spring-context/src/main/java/org/springframework/context/support/SimpleThreadScope.java +++ b/spring-context/src/main/java/org/springframework/context/support/SimpleThreadScope.java @@ -55,14 +55,7 @@ public class SimpleThreadScope implements Scope { private static final Log logger = LogFactory.getLog(SimpleThreadScope.class); - private final ThreadLocal> threadScope = - new NamedThreadLocal<>("SimpleThreadScope") { - @Override - protected Map initialValue() { - return new HashMap<>(); - } - }; - + private final ThreadLocal> threadScope = NamedThreadLocal.withInitial("SimpleThreadScope", HashMap::new); @Override public Object get(String name, ObjectFactory objectFactory) { diff --git a/spring-core/src/main/java/org/springframework/core/NamedThreadLocal.java b/spring-core/src/main/java/org/springframework/core/NamedThreadLocal.java index 3d211a82d02..f90a572d80c 100644 --- a/spring-core/src/main/java/org/springframework/core/NamedThreadLocal.java +++ b/spring-core/src/main/java/org/springframework/core/NamedThreadLocal.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,9 @@ package org.springframework.core; +import java.util.Objects; +import java.util.function.Supplier; + import org.springframework.util.Assert; /** @@ -23,6 +26,7 @@ import org.springframework.util.Assert; * as {@link #toString()} result (allowing for introspection). * * @author Juergen Hoeller + * @author Qimiao Chen * @since 2.5.2 * @param the value type * @see NamedInheritableThreadLocal @@ -41,9 +45,44 @@ public class NamedThreadLocal extends ThreadLocal { this.name = name; } + /** + * Creates a named thread local variable. The initial value of the variable is + * determined by invoking the {@code get} method on the {@code Supplier}. + * + * @param the type of the named thread local's value + * @param supplier the supplier to be used to determine the initial value + * @return a new named thread local variable + * @throws NullPointerException if the specified supplier is null + * @since 5.2.5 + */ + public static ThreadLocal withInitial(String name, Supplier supplier) { + return new SuppliedNamedThreadLocal<>(name, supplier); + } + @Override public String toString() { return this.name; } + + /** + * An extension of NamedThreadLocal that obtains its initial value from + * the specified {@code Supplier}. + * @param the type of the named thread local's value + */ + static final class SuppliedNamedThreadLocal extends NamedThreadLocal { + + private final Supplier supplier; + + SuppliedNamedThreadLocal(String name, Supplier supplier) { + super(name); + this.supplier = Objects.requireNonNull(supplier); + } + + @Override + protected T initialValue() { + return this.supplier.get(); + } + } + }