diff --git a/org.springframework.context/src/main/java/org/springframework/context/support/SimpleThreadScope.java b/org.springframework.context/src/main/java/org/springframework/context/support/SimpleThreadScope.java new file mode 100644 index 00000000000..c45f2c43129 --- /dev/null +++ b/org.springframework.context/src/main/java/org/springframework/context/support/SimpleThreadScope.java @@ -0,0 +1,82 @@ +/* + * Copyright 2002-2009 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.context.support; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.springframework.beans.factory.ObjectFactory; +import org.springframework.beans.factory.config.Scope; +import org.springframework.core.NamedThreadLocal; + +/** + * Thread-backed {@link Scope} implementation. + * + *

Note that the SimpleThreadScope does not clean up any objects associated + * with it. As such, it's typically preferable to use the {@link org.springframework.web.context.request.RequestScope} + * in Web environments. + * + *

For a implementation of a thread-based Scope with support for destruction callbacks, refer to this module. + * + * @author Eugene Kuleshov + * @author Arjen Poutsma + * @since 3.0 + */ +public class SimpleThreadScope implements Scope { + + private static final Log logger = LogFactory.getLog(SimpleThreadScope.class); + + private static final ThreadLocal> threadScope = + new NamedThreadLocal>("SimpleThreadScope") { + @Override + protected Map initialValue() { + return new HashMap(); + } + }; + + public Object get(String name, ObjectFactory objectFactory) { + Map scope = threadScope.get(); + Object object = scope.get(name); + if (object == null) { + object = objectFactory.getObject(); + scope.put(name, object); + } + return object; + } + + public Object remove(String name) { + Map scope = threadScope.get(); + return scope.remove(name); + } + + public void registerDestructionCallback(String name, Runnable callback) { + logger.warn("SimpleThreadScope does not support descruction callbacks. " + + "Consider using a RequestScope in a Web environment"); + } + + public Object resolveContextualObject(String key) { + return null; + } + + public String getConversationId() { + return Thread.currentThread().getName(); + } +} diff --git a/org.springframework.context/src/test/java/org/springframework/context/support/SimpleThreadScopeTest.java b/org.springframework.context/src/test/java/org/springframework/context/support/SimpleThreadScopeTest.java new file mode 100644 index 00000000000..01d95795fa5 --- /dev/null +++ b/org.springframework.context/src/test/java/org/springframework/context/support/SimpleThreadScopeTest.java @@ -0,0 +1,72 @@ +/* + * Copyright 2002-2009 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.context.support; + +import static org.junit.Assert.*; +import org.junit.Before; +import org.junit.Test; + +import org.springframework.beans.TestBean; +import org.springframework.context.ApplicationContext; + +/** + * @author Arjen Poutsma + */ +public class SimpleThreadScopeTest { + + private ApplicationContext applicationContext; + + @Before + public void setUp() { + applicationContext = new ClassPathXmlApplicationContext("simpleThreadScopeTests.xml", getClass()); + } + + @Test + public void getFromScope() throws Exception { + String name = "threadScopedObject"; + TestBean bean = (TestBean) this.applicationContext.getBean(name); + assertNotNull(bean); + assertSame(bean, this.applicationContext.getBean(name)); + TestBean bean2 = (TestBean) this.applicationContext.getBean(name); + assertSame(bean, bean2); + } + + @Test + public void getMultipleInstances() throws Exception { + final TestBean[] beans = new TestBean[2]; + Thread thread1 = new Thread(new Runnable() { + public void run() { + beans[0] = applicationContext.getBean("threadScopedObject", TestBean.class); + } + }); + Thread thread2 = new Thread(new Runnable() { + public void run() { + beans[1] = applicationContext.getBean("threadScopedObject", TestBean.class); + } + }); + thread1.start(); + thread2.start(); + + Thread.sleep(200); + + assertNotNull(beans[0]); + assertNotNull(beans[1]); + + assertNotSame(beans[0], beans[1]); + } + +} diff --git a/org.springframework.web/src/test/resources/org/springframework/web/context/request/requestScopeTests.xml b/org.springframework.context/src/test/resources/org/springframework/context/support/simpleThreadScopeTests.xml similarity index 74% rename from org.springframework.web/src/test/resources/org/springframework/web/context/request/requestScopeTests.xml rename to org.springframework.context/src/test/resources/org/springframework/context/support/simpleThreadScopeTests.xml index f2d06c527f4..2b71bd30014 100644 --- a/org.springframework.web/src/test/resources/org/springframework/web/context/request/requestScopeTests.xml +++ b/org.springframework.context/src/test/resources/org/springframework/context/support/simpleThreadScopeTests.xml @@ -1,13 +1,22 @@ - - - + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> + + + + + + + + + + + +