gerrytan
gerrytan

Reputation: 41143

Spring annotation based caching

My Spring app consists of two context xml config files, the first one root-context.xml only scans non-@Controller annotated beans:

<beans ...>
  <context:component-scan base-package="com.myapp.test">
    <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
  </context:component-scan>
</beans>

While the second one servlet-context.xml contains all spring-mvc setup and scans @Controller annotated beans

<beans:beans xmlns="http://www.springframework.org/schema/mvc" ...>
  <annotation-driven />
  <context:component-scan base-package="com.myapp.test">
    <context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
  </context:component-scan>
  ...
</beans:beans>

DispatcherServlet config on web.xml looks like this

<web-app ...>
  ...
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring/root-context.xml</param-value>
  </context-param>

  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <servlet>
    <servlet-name>appServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>

  ...

</web-app>

I wanted to try annotation based caching so I added following beans definition to root-context.xml

<cache:annotation-driven/>

<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
  <property name="caches">
    <set>
      <bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="foo"/>
    </set>
  </property>
</bean>

And test this with a @Service annotated class which should be scanned by root-context.xml

@Service
public FooService {
  @Cacheable("foo")
  public int getFoo() {
    System.out.println("cache miss");
    return new Random().nextInt(50);
  }
}

But the getFoo() method call never gets cached, I always get random number everytime.

If however I scanned all my beans on servlet-context.xml and relocated my caching beans definition there it works.

What may cause this? There's definitely something I don't yet understand about caching annotations.

Upvotes: 4

Views: 1677

Answers (1)

Boris Treukhov
Boris Treukhov

Reputation: 17784

In your servlet-controller.xml you are not excluding @Component beans when doing context:component-scan

<context:component-scan base-package="com.myapp.test">
    <context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
  </context:component-scan>

you should add use-default-filters="false"

 <context:component-scan base-package="com.myapp.test" use-default-filters="false">
        <context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
  </context:component-scan>

to avoid bean shadowing.

Upvotes: 5

Related Questions