在将spring升级到version 4之后,我们的自定义密钥生成器停止工作。在迁移之前,重写"generate“方法的代码被执行,但是在迁移到Spring4.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类,它有一个私有属性:私有KeyGenerator keyGenerator =新的SimpleKeyGenerator();这个类在keyGenerator属性上有一个setter方法,并且我看到当上下文启动时,这个setter方法是用我的自定义CacheKeyGenerator调用的,所以我的结论是我的配置是正确的,并且在配置中没有问题。我还看到,当需要键加法时,keyGenerator属性“丢失”了"CacheKeyGenerator“值,并具有"SimpleKeyGenerator”。这解释了为什么我的自定义代码从未被执行,但我不明白为什么keyGenerator属性指向SimpleKeyGenerator。这似乎是一个SPring错误。有什么问题吗?
发布于 2014-07-07 15:43:11
在查看了您发送的示例代码之后,我发现您有两个问题:
@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注释,因为它可以覆盖您的FacadeImpl(从FacadeImpl中删除它)。
组件扫描覆盖
您有一个root-context.xml和一个servlet-context.xml配置,但是这两种配置都在扫描相同的包。缓存配置是在root-context.xml中声明的,因此这个上下文中的bean已经应用了缓存,但是,bean在没有应用缓存的servlet-context.xml中被复制(因为它们再次被扫描)。
由于您似乎并不真正需要根/web分离,所以我建议只创建一个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"/>Tip
最后一件看起来有点奇怪的事情是,您依赖于密钥的toString()方法。我很想直接使用SimpleKey类来满足您的需要:
public Object generate(Object target, Method method, Object... params) {
return new SimpleKey(method.getName(), params);
}如果您可以公开提供复制问题的示例代码,并将其作为堆栈溢出的链接使用,那么您也更有可能获得此类问题的帮助。GitHub是托管示例项目的好地方。另外,在您确定之前,请不要大喊它是BUG :)
https://stackoverflow.com/questions/24613528
复制相似问题