使用依赖jar中的Spring CacheManager

时间:2015-02-18 09:34:12

标签: java spring caching jar redis

我有几个WAR项目,包括对某个实用程序JAR项目的依赖。我希望能够通过使用spring的@Cacheable注释来缓存实用程序项目中的某些方法,所以我尝试在实用程序项目中创建一个配置文件,在那里我可以定义一个可以处理方法缓存的CacheManager bean。配置文件如下所示:

(请注意,我正在使用Redis缓存实现,但其他缓存提供程序的spring配置应该非常相似)

@Configuration
@EnableCaching
public class RedisConfig {

    @Value("${redis.hostUrl}")
    private String hostUrl = null;

    @Value("${redis.port}")
    private Integer port = null;

    @Value("${redis.defaultExpiration}")
    private Integer defaultExpiration = null;


    @Bean
    public JedisConnectionFactory redisConnectionFactory() {
        JedisConnectionFactory = new JedisConnectionFactory();
        // Defaults
        redisConnectionFactory.setHostName(hostUrl);
        redisConnectionFactory.setPort(port);
        return redisConnectionFactory;
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory cf) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setConnectionFactory(cf);
        return redisTemplate;
    }

    @Bean
    public CacheManager cacheManager(RedisTemplate redisTemplate) {
        RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);

        // Number of seconds before expiration. Defaults to unlimited (0)
        cacheManager.setDefaultExpiration(defaultExpiration);

        cacheManager.setUsePrefix(true);

        List<String> cacheNames = new ArrayList<String>();
        cacheNames.add("testing");
        cacheManager.setCacheNames(cacheNames);
        return cacheManager;
    }
}

我很确定配置本身不是问题,因为我在其他WAR模块中有类似的配置文件,并且缓存可以正常工作。但是,由于这是一个由其他模块加载的JAR,我的猜测是Spring没有接收到CacheManager。

在项目A中,它依赖于utils项目,我有一个类似下面的方法(为简单起见而编辑;忽略无效语法):

@RequestMapping(...)
@ResponseBody
public Dto methodA(...) {

    //The relevant part
    testCachedMethod(value);
    cachedMethodFromProjectB(value);

}

@Cacheable(value="testing")
public String testCachedMethod(String value) {
    return value;
}

项目B是另一个具有自己的CacheManager(不依赖于utils)的WAR,并且具有使用@Cacheable缓存的类似方法。如果我点击了项目A的方法A,项目B中的缓存可以正确存储,但是项目A中的cachedMethod不会在缓存中存储任何内容(而且utils项目中的方法也没有使用@Cacheable注释)。我还尝试了另一种方法,直接在项目A上创建CacheManager,但它也无法在utils项目中缓存带注释的方法(我更喜欢在utils项目中声明管理器,以便其他模块可以重用它)。

我知道Spring正在初始化utils项目中的bean,因为如果项目A的上下文属性占位符没有从缓存配置文件中找到@Value注释的属性文件,则项目A无法运行。所以我认为CacheManager bean在那里,但不知何故它不起作用。关于我做错了什么的想法,或者甚至可以使用依赖JAR中的CacheManager(如果可能,使用Java配置)?我正在使用Spring 3.2.0.RELEASE。

现在试图解决这个问题几天,所以非常感谢任何帮助。

1 个答案:

答案 0 :(得分:2)

原来是spring cache abstraction的默认代理模式的问题。缓存注释不起作用的所有方法都被同一对象中的其他方法调用。我可以使用CacheManager bean上的@Autowire正确操作依赖jar项目中的缓存,并手动执行缓存操作。虽然应该可以通过启用AspectJ编织模式来使用注释,但我不希望通过处理依赖模块中的编织来增加更多的复杂性。