1

将我们的 spring 升级到版本 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); 
}

}

附加信息:调试代码后,我看到每次调用“生成”方法时,它仅在 SimpleKeyGenerator 中执行,而不在我的自定义 CacheKeyGenerator 类中执行。我试图理解为什么,所以我做了一些调试。在调试时,我看到有 org.springframework.cache.interceptor.CacheAspectSupport 类,它有一个私有属性: private KeyGenerator keyGenerator = new SimpleKeyGenerator(); 这个类在 keyGenerator 属性上有一个 setter 方法,我看到当上下文启动时,这个 setter 方法是用我自定义的 CacheKeyGenerator 调用的,所以我断定我的配置是正确的,问题不在配置中。我还看到,当需要生成密钥时,keyGenerator 属性“丢失”了“CacheKeyGenerator”值并具有“

4

1 回答 1

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)。

组件扫描覆盖

您有 aroot-context.xml和 aservlet-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>

root-context.xml2)通过将以下内容添加到您的文件中,直接导入您的文件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 :)

于 2014-07-07T15:43:11.903 回答