Scoped Bean Dependencies

January 04, 2011

Spring provides multiple bean scopes, and though singleton is predominant it is sometimes useful to inject non-singleton (and non-prototype) dependencies

In this short example, I show how to dependency inject a request-scoped bean into a Spring MVC controller, a singleton bean.

Consider the following controller, which has a single dependency of type Metadata.

MetadataController.java:

@Controller
public class MetadataController {

  @Autowired
  private Metadata metadata;

  @RequestMapping(value = "/metadata")
  public void metadata(Model model) {
    model.addAttribute("date", metadata.getDate());
  }
}

The Metadata and a simple implementation allow storage and retrieval of a Date.

Metadata.java:

public interface Metadata {
  public String getDate();
}

MetadataImpl.java:

public class MetadataImpl implements Metadata {

  private final Date date;

  public MetadataImpl(Date date) {
    this.date = date;
  }

  @Override
  public String getDate() {
    return date.toString();
  }
}

These beans are wired into a basic Spring MVC application.

spring-mvc-servlet.xml:

<mvc:annotation-driven />

<bean
  class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="prefix" value="/WEB-INF/jsp/" />
  <property name="suffix" value=".jsp" />
</bean>

<context:component-scan base-package="com.earldouglas.requestscope" />

<context:annotation-config />

<bean class="com.earldouglas.requestscope.MetadataImpl" scope="request">
  <constructor-arg>
    <bean class="java.util.Date" />
  </constructor-arg>
  <aop:scoped-proxy proxy-target-class="false" />
</bean>

The only things out of the ordinary here are the scope of the MetadataImpl bean, which is set to request, and the <aop:scoped-proxy /> element within it.

The request scope tells Spring to instantiate a new MetadataImpl bean with each Web request, and to make that bean available only within the context of that Web request.

The <aop:scoped-proxy /> element tells Spring that this bean is not to be injected as a dependency directly, but instead an AOP proxy of this bean is to be injected in its place. This allows Spring to make each request-scoped MetadataImpl dependency available to the Web request thread to which it corresponds. The proxy-target-class="false" attribute tells Spring not to use a CGLIB proxy, but a JDK dynamic proxy instead.

A simple view displays the Date, which is created for each request the controller receives.

metadata.jsp:

<h1>Metadata</h1>
Date: <c:out value="${date}" />