Spring annotation based caching

java, spring

Solution

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.

Problem

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.

Original source