将弹簧升级到版本4后,我们的自定义密钥生成器停止工作。 在迁移之前,我们执行了覆盖“generate”方法的代码,但是在迁移到spring 4.0.5之后,代码根本没有执行。 相反,我看到SimpleKeyGenerator始终是执行的。 这是春天的虫子吗?为什么我不能像以前的版本那样用我自己的代码覆盖generate方法?
来自根上下文的示例:
<cache:annotation-driven key-generator="cacheKeyGenerator" />
<bean id="cacheKeyGenerator" class="com.poalim.xp.general.cache.CacheKeyGenerator"/>
来自java密钥生成的样本(迁移前)
public class CacheKeyGenerator extends DefaultKeyGenerator implements ApplicationContextAware {
public Object generate(Object target, Method method, Object... params) {
return method.getName() + super.generate(target, method, params);
}
}
迁移后的示例代码
public class CacheKeyGenerator extends SimpleKeyGenerator implements ApplicationContextAware {
public Object generate(Object target, Method method, Object... params) {
return method.getName() + super.generate(target, method, params);
}
}
其他信息: 在调试代码之后,我看到每次调用“generate”方法时, 它仅在SimpleKeyGenerator中执行,而不是在我的自定义CacheKeyGenerator类中执行。 我试着理解为什么,所以我做了一些调试。 在调试时,我看到有org.springframework.cache.interceptor.CacheAspectSupport类, 具有私有属性:private KeyGenerator keyGenerator = new SimpleKeyGenerator(); 这个类在keyGenerator属性上有一个setter方法,我在上下文启动时看到了 使用我的自定义CacheKeyGenerator调用此setter方法,因此我得出结论,我的配置是正确的,并且问题不在配置中。 我还看到,当需要密钥ganeration时,keyGenerator属性“丢失”了“CacheKeyGenerator”值并具有“SimpleKeyGenerator”。 这解释了为什么我的自定义代码永远不会执行,但我不明白为什么keyGenerator属于SimpleKeyGenerator。 这似乎是一个SPring BUG。 有什么问题?
答案 0 :(得分:2)
查看了您通过电子邮件发送的示例代码,我发现您有两个问题:
<强> @EnableCaching 强>
当您使用Java配置时,@EnableCaching
注释旨在用作XML配置的替代。例如:
@Configuration
@EnableCaching
public class AppConfig implements CachingConfigurer {
@Bean
@Override
public CacheManager cacheManager() {
// configure and return an implementation of Spring's CacheManager SPI
SimpleCacheManager cacheManager = new SimpleCacheManager();
cacheManager.addCaches(Arrays.asList(new ConcurrentMapCache("default")));
return cacheManager;
}
@Bean
@Override
public KeyGenerator keyGenerator() {
// configure and return an implementation of Spring's KeyGenerator SPI
return new MyKeyGenerator();
}
}
由于您使用的是XML配置:
<cache:annotation-driven key-generator="cacheKeyGenerator" />
您不应在代码中的任何位置添加@EnableCaching
注释,因为它可以覆盖您的XML(将其从FacadeImpl
中删除)。
组件扫描覆盖
您有root-context.xml
和servlet-context.xml
配置,但这两种配置都在扫描相同的包。您在root-context.xml
中声明了缓存配置,因此在此上下文中的bean应用了缓存,但是,在servlet-context.xml
中没有应用缓存的bean会被复制(因为它们会被再次扫描)。
由于您似乎不需要根/网络分离,我建议您只创建一个ApplicationContext
。要做到这一点:
1)从web.xml
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:root-context.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
2)通过将以下内容添加到root-context.xml
servlet-context.xml
文件
<beans:import resource="classpath:root-context.xml"/>
提示强>
最后看起来有点奇怪的是你依赖于密钥的toString()
方法。我很想直接使用SimpleKey
课程来满足您的需求:
public Object generate(Object target, Method method, Object... params) {
return new SimpleKey(method.getName(), params);
}
如果您可以公开提供复制问题的示例代码并将其作为堆栈溢出链接提供,那么您也更有可能获得此类问题的帮助。 GitHub是举办样本项目的绝佳场所。另外,请确保大喊它是BUG,直到您确定:)