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 34454f236c..14357c9f74 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 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. @@ -29,9 +29,14 @@ import org.springframework.core.NamedThreadLocal; /** * A simple thread-backed {@link Scope} implementation. * - *
Note: {@code SimpleThreadScope} does not clean up - * any objects associated with it. As such, it is typically preferable to - * use {@link org.springframework.web.context.request.RequestScope RequestScope} + *
NOTE: This thread scope is not registered by default in common contexts. + * Instead, you need to explicitly assign it to a scope key in your setup, either through + * {@link org.springframework.beans.factory.config.ConfigurableBeanFactory#registerScope} + * or through a {@link org.springframework.beans.factory.config.CustomScopeConfigurer} bean. + * + *
{@code SimpleThreadScope} does not clean up any objects associated with it. + * As such, it is typically preferable to use + * {@link org.springframework.web.context.request.RequestScope RequestScope} * in web environments. * *
For an implementation of a thread-based {@code Scope} with support for diff --git a/spring-tx/src/main/java/org/springframework/transaction/support/SimpleTransactionScope.java b/spring-tx/src/main/java/org/springframework/transaction/support/SimpleTransactionScope.java new file mode 100644 index 0000000000..60ad8426a1 --- /dev/null +++ b/spring-tx/src/main/java/org/springframework/transaction/support/SimpleTransactionScope.java @@ -0,0 +1,111 @@ +/* + * Copyright 2002-2015 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.transaction.support; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.springframework.beans.factory.ObjectFactory; +import org.springframework.beans.factory.config.Scope; + +/** + * A simple transaction-backed {@link Scope} implementation, delegating to + * {@link TransactionSynchronizationManager}'s resource binding mechanism. + * + *
NOTE: Like {@link org.springframework.context.support.SimpleThreadScope},
+ * this transaction scope is not registered by default in common contexts. Instead,
+ * you need to explicitly assign it to a scope key in your setup, either through
+ * {@link org.springframework.beans.factory.config.ConfigurableBeanFactory#registerScope}
+ * or through a {@link org.springframework.beans.factory.config.CustomScopeConfigurer} bean.
+ *
+ * @author Juergen Hoeller
+ * @since 4.2
+ * @see org.springframework.context.support.SimpleThreadScope
+ * @see org.springframework.beans.factory.config.ConfigurableBeanFactory#registerScope
+ * @see org.springframework.beans.factory.config.CustomScopeConfigurer
+ */
+public class SimpleTransactionScope implements Scope {
+
+ @Override
+ public Object get(String name, ObjectFactory> objectFactory) {
+ ScopedObjectsHolder scopedObjects = (ScopedObjectsHolder) TransactionSynchronizationManager.getResource(this);
+ if (scopedObjects == null) {
+ scopedObjects = new ScopedObjectsHolder();
+ TransactionSynchronizationManager.registerSynchronization(new CleanupSynchronization());
+ TransactionSynchronizationManager.bindResource(this, scopedObjects);
+ }
+ Object scopedObject = scopedObjects.scopedInstances.get(name);
+ if (scopedObject == null) {
+ scopedObject = objectFactory.getObject();
+ scopedObjects.scopedInstances.put(name, scopedObject);
+ }
+ return scopedObject;
+ }
+
+ @Override
+ public Object remove(String name) {
+ ScopedObjectsHolder scopedObjects = (ScopedObjectsHolder) TransactionSynchronizationManager.getResource(this);
+ if (scopedObjects != null) {
+ scopedObjects.destructionCallbacks.remove(name);
+ return scopedObjects.scopedInstances.remove(name);
+ }
+ else {
+ return null;
+ }
+ }
+
+ @Override
+ public void registerDestructionCallback(String name, Runnable callback) {
+ ScopedObjectsHolder scopedObjects = (ScopedObjectsHolder) TransactionSynchronizationManager.getResource(this);
+ if (scopedObjects != null) {
+ scopedObjects.destructionCallbacks.put(name, callback);
+ }
+ }
+
+ @Override
+ public Object resolveContextualObject(String key) {
+ return null;
+ }
+
+ @Override
+ public String getConversationId() {
+ return TransactionSynchronizationManager.getCurrentTransactionName();
+ }
+
+
+ static class ScopedObjectsHolder {
+
+ final Map