https://m.blog.naver.com/PostView.nhn?blogId=gngh0101&logNo=222344239921&proxyReferer=https:%2F%2Fblog.naver.com%2Fgngh0101%2F222344239921

public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry { /** * Scope identifier for the standard singleton scope: {@value}. * <p>Custom scopes can be added via {@code registerScope}. * @see #registerScope / String SCOPE_SINGLETON = "singleton"; /* * Scope identifier for the standard prototype scope: {@value}. * <p>Custom scopes can be added via {@code registerScope}. * @see #registerScope */ String SCOPE_PROTOTYPE = "prototype"; void registerScope(String scopeName, Scope scope); }

public interface WebApplicationContext extends ApplicationContext { /** * Scope identifier for request scope: "request". * Supported in addition to the standard scopes "singleton" and "prototype". / String SCOPE_REQUEST = "request"; /* * Scope identifier for session scope: "session". * Supported in addition to the standard scopes "singleton" and "prototype". / String SCOPE_SESSION = "session"; /* * Scope identifier for the global web application scope: "application". * Supported in addition to the standard scopes "singleton" and "prototype". */ String SCOPE_APPLICATION = "application"; } org.springframework.web.context

: ServletWebServerApplicationContext 을 상속한 것을 확인할 수 있다.

public class ServletWebServerApplicationContext extends GenericWebApplicationContext implements ConfigurableWebServerApplicationContext { @Override protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { beanFactory.addBeanPostProcessor(new WebApplicationContextServletContextAwareProcessor(this)); beanFactory.ignoreDependencyInterface(ServletContextAware.class); registerWebApplicationScopes(); } }

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext { @Override public void refresh() throws BeansException, IllegalStateException { .... .... try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); .... .... } }

public abstract class WebApplicationContextUtils { public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory, @Nullable ServletContext sc) { beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope()); beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope()); if (sc != null) { ServletContextScope appScope = new ServletContextScope(sc); beanFactory.registerScope(WebApplicationContext.SCOPE_APPLICATION, appScope); // Register as ServletContext attribute, for ContextCleanupListener to detect it. sc.setAttribute(ServletContextScope.class.getName(), appScope); } beanFactory.registerResolvableDependency(ServletRequest.class, new RequestObjectFactory()); beanFactory.registerResolvableDependency(ServletResponse.class, new ResponseObjectFactory()); beanFactory.registerResolvableDependency(HttpSession.class, new SessionObjectFactory()); beanFactory.registerResolvableDependency(WebRequest.class, new WebRequestObjectFactory()); if (jsfPresent) { FacesDependencyRegistrar.registerFacesDependencies(beanFactory); } } }

public class RequestScope extends AbstractRequestAttributesScope { @Override protected int getScope() { return RequestAttributes.SCOPE_REQUEST; } /** * There is no conversation id concept for a request, so this method * returns {@code null}. */ @Override @Nullable public String getConversationId() { return null; } }

public abstract class AbstractRequestAttributesScope implements Scope { @Override public Object get(String name, ObjectFactory<?> objectFactory) { RequestAttributes attributes = RequestContextHolder.currentRequestAttributes(); Object scopedObject = attributes.getAttribute(name, getScope()); if (scopedObject == null) { scopedObject = objectFactory.getObject(); attributes.setAttribute(name, scopedObject, getScope()); // Retrieve object again, registering it for implicit session attribute updates. // As a bonus, we also allow for potential decoration at the getAttribute level. Object retrievedObject = attributes.getAttribute(name, getScope()); if (retrievedObject != null) { // Only proceed with retrieved object if still present (the expected case). // If it disappeared concurrently, we return our locally created instance. scopedObject = retrievedObject; } } return scopedObject; } }

public class SessionScope extends AbstractRequestAttributesScope { @Override protected int getScope() { return RequestAttributes.SCOPE_SESSION; } @Override public String getConversationId() { return RequestContextHolder.currentRequestAttributes().getSessionId(); } @Override public Object get(String name, ObjectFactory<?> objectFactory) { Object mutex = RequestContextHolder.currentRequestAttributes().getSessionMutex(); synchronized (mutex) { return super.get(name, objectFactory); } } @Override @Nullable public Object remove(String name) { Object mutex = RequestContextHolder.currentRequestAttributes().getSessionMutex(); synchronized (mutex) { return super.remove(name); } } }

public class ServletContextScope implements Scope, DisposableBean { private final ServletContext servletContext; public ServletContextScope(ServletContext servletContext) { Assert.notNull(servletContext, "ServletContext must not be null"); this.servletContext = servletContext; } @Override public Object get(String name, ObjectFactory<?> objectFactory) { Object scopedObject = this.servletContext.getAttribute(name); if (scopedObject == null) { scopedObject = objectFactory.getObject(); this.servletContext.setAttribute(name, scopedObject); } return scopedObject; } .... .... }

나머지는 전부 custom이다. mvc의 경우 request / session / application 3가지 scope을 추가적으로 사용한다.

hotire/spring-core