001/* 002 * Copyright 2002-2017 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.web.context.request; 018 019import org.springframework.beans.factory.ObjectFactory; 020import org.springframework.beans.factory.config.Scope; 021 022/** 023 * Abstract {@link Scope} implementation that reads from a particular scope 024 * in the current thread-bound {@link RequestAttributes} object. 025 * 026 * <p>Subclasses simply need to implement {@link #getScope()} to instruct 027 * this class which {@link RequestAttributes} scope to read attributes from. 028 * 029 * <p>Subclasses may wish to override the {@link #get} and {@link #remove} 030 * methods to add synchronization around the call back into this super class. 031 * 032 * @author Rod Johnson 033 * @author Juergen Hoeller 034 * @author Rob Harrop 035 * @since 2.0 036 */ 037public abstract class AbstractRequestAttributesScope implements Scope { 038 039 @Override 040 public Object get(String name, ObjectFactory<?> objectFactory) { 041 RequestAttributes attributes = RequestContextHolder.currentRequestAttributes(); 042 Object scopedObject = attributes.getAttribute(name, getScope()); 043 if (scopedObject == null) { 044 scopedObject = objectFactory.getObject(); 045 attributes.setAttribute(name, scopedObject, getScope()); 046 // Retrieve object again, registering it for implicit session attribute updates. 047 // As a bonus, we also allow for potential decoration at the getAttribute level. 048 Object retrievedObject = attributes.getAttribute(name, getScope()); 049 if (retrievedObject != null) { 050 // Only proceed with retrieved object if still present (the expected case). 051 // If it disappeared concurrently, we return our locally created instance. 052 scopedObject = retrievedObject; 053 } 054 } 055 return scopedObject; 056 } 057 058 @Override 059 public Object remove(String name) { 060 RequestAttributes attributes = RequestContextHolder.currentRequestAttributes(); 061 Object scopedObject = attributes.getAttribute(name, getScope()); 062 if (scopedObject != null) { 063 attributes.removeAttribute(name, getScope()); 064 return scopedObject; 065 } 066 else { 067 return null; 068 } 069 } 070 071 @Override 072 public void registerDestructionCallback(String name, Runnable callback) { 073 RequestAttributes attributes = RequestContextHolder.currentRequestAttributes(); 074 attributes.registerDestructionCallback(name, callback, getScope()); 075 } 076 077 @Override 078 public Object resolveContextualObject(String key) { 079 RequestAttributes attributes = RequestContextHolder.currentRequestAttributes(); 080 return attributes.resolveReference(key); 081 } 082 083 084 /** 085 * Template method that determines the actual target scope. 086 * @return the target scope, in the form of an appropriate 087 * {@link RequestAttributes} constant 088 * @see RequestAttributes#SCOPE_REQUEST 089 * @see RequestAttributes#SCOPE_SESSION 090 * @see RequestAttributes#SCOPE_GLOBAL_SESSION 091 */ 092 protected abstract int getScope(); 093 094}