- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试在抽象类中使用 Spring Cache,但它不起作用,因为据我所知,Spring 正在抽象类中搜索 CacheNames。我有一个使用服务层和 Dao 层的 REST API。这个想法是为每个子类使用不同的缓存名称。
我的抽象服务类如下所示:
@Service
@Transactional
public abstract class AbstractService<E> {
...
@Cacheable
public List<E> findAll() {
return getDao().findAll();
}
}
抽象类的扩展如下所示:
@Service
@CacheConfig(cacheNames = "textdocuments")
public class TextdocumentsService extends AbstractService<Textdocuments> {
...
}
因此,当我使用这段代码启动应用程序时,Spring 给出了以下异常:
Caused by: java.lang.IllegalStateException: No cache names could be detected on 'public java.util.List foo.bar.AbstractService.findAll()'. Make sure to set the value parameter on the annotation or declare a @CacheConfig at the class-level with the default cache name(s) to use.
at org.springframework.cache.annotation.SpringCacheAnnotationParser.validateCacheOperation(SpringCacheAnnotationParser.java:240) ~[spring-context-4.1.6.RELEASE.jar:?]
我认为发生这种情况是因为 Spring 正在抽象类上搜索 CacheName,尽管它是在子类上声明的。
尝试使用
@Service
@Transactional
@CacheConfig
public abstract class AbstractService<E> {
}
导致相同的异常;使用
@Service
@Transactional
@CacheConfig(cacheNames = "abstractservice")
public abstract class AbstractService<E> {
}
没有异常,但是 Spring Cache 为每个子类使用相同的缓存名称,并忽略在子类上定义的缓存名称。有什么想法可以解决这个问题吗?
最佳答案
此问题已在 another question 中解决并且与抽象类无关,而与框架确定要使用哪个缓存的能力有关。
长话短说(引自 Spring documentation)您缺少适用于您的抽象类层次结构的 CacheResolver
:
Since Spring 4.1, the value attribute of the cache annotations are no longer mandatory, since this particular information can be provided by the CacheResolver regardless of the content of the annotation.
因此,您的抽象类应该定义一个缓存解析器,而不是直接声明缓存名称。
abstract class Repository<T> {
// .. some methods omitted for brevity
@Cacheable(cacheResolver = CachingConfiguration.CACHE_RESOLVER_NAME)
public List<T> findAll() {
return getDao().findAll();
}
}
解析器确定用于拦截方法调用的缓存实例。一个非常天真的实现可以获取目标存储库 bean(按名称)并将其用作缓存名称
class RuntimeCacheResolver
extends SimpleCacheResolver {
protected RuntimeCacheResolver(CacheManager cacheManager) {
super(cacheManager);
}
@Override
protected Collection<String> getCacheNames(CacheOperationInvocationContext<?> context) {
return Arrays.asList(context.getTarget().getClass().getSimpleName());
}
}
这样的解析器需要一个明确的配置:
@Configuration
@EnableCaching
class CachingConfiguration extends CachingConfigurerSupport {
final static String CACHE_RESOLVER_NAME = "simpleCacheResolver";
@Bean
@Override
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager();
}
@Bean(CACHE_RESOLVER_NAME)
public CacheResolver cacheResolver(CacheManager cacheManager) {
return new RuntimeCacheResolver(cacheManager);
}
}
我已经 create a Gist其中更详细地描述了整个概念。
免责声明
以上片段仅用于演示,旨在提供指导而非提供完整的解决方案。上面的缓存解析器实现非常幼稚,没有考虑很多东西(比如方法参数等)。我永远不会在生产环境中使用它。
Spring 处理缓存的方式是通过代理,其中 @Cacheable
注释声明缓存,以及在运行时处理的命名信息。缓存通过提供给缓存解析器的运行时信息来解析(毫不奇怪,它与经典 AOP 的 InvocationContext 有一些相似之处)。
public interface CacheOperationInvocationContext<O extends BasicOperation> {
O getOperation();
Object getTarget();
Method getMethod();
Object[] getArgs();
}
通过 getTarget()
方法可以找出代理了哪个 bean,但在现实生活中,应该考虑更多信息,以提供可靠的缓存(如方法参数, ETC)。
关于java - Spring Cache 不适用于抽象类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36977643/
我对 java 中的抽象有点困惑。 我查了很多页面说抽象就是数据隐藏(隐藏实现)。 我对抽象的理解是它是“部分实现”。只需在抽象类/接口(interface)中定义您需要的内容,然后扩展/实现它们并添
我是 Ruby 的新手,主要来自 C# 和 ActionScript 3(以及其他语言)。我对抽象功能很好奇。具体来说,包装和抽象 Ruby 的 FTP 和 SFTP 库。 我四处搜索,发现了一个名为
目录 Java基础知识(抽象) 抽象 抽象定义 abstract的使用 定义抽象类
这个月我花了一些时间与 Emacs Lisp 进行斗争,试图获得更好地满足我需求的自动缩进。令人惊讶的是,大多数缩进代码是多么低级。我只看到了很少的抽象,例如 搜索不在字符串或注释中的第一个正则表达式
我有以下内容: public abstract class Foo{ //contents of Foo // ... public class Bar extends
我有三个类(class)(A 类、B 类和 C 类)。 类 A 调用 B 的实例并运行 start()。 B类扩展了Thread,因此当调用start()时,run()方法中的任何内容都会被执行。 在
这个问题已经有答案了: Calling a subclass method from superclass (5 个回答) 已关闭 7 年前。 Klasse1是一个抽象类,有一个 foo()方法。 K
我有一个这样的函数: def test(): x = "3" # In actual code, this is computed if x is None: retu
我有两个基类之间的关系: public abstract class RecruiterBase { // Properties declare here // Constructors de
这是我第一次发帖,但我遇到了很多问题。我目前有一个带有标题的 AbstractDevice 类: public abstract class AbstractDevice> implements De
我有一个 MotorDefinition 类和一个名为 Motor 的抽象类: class MotorDefinition { public: MotorDefinition(int p1,
是否有任何方法可以在这种代码(sass)中制定 css 的抽象规则: #cottage-image-gallery input:nth-of-type(1):checked ~ label:nth-o
是否可以声明一个已知的基类型并允许传输所有派生类型? [ServiceContract] public interface IService { [OperationContract]
我目前正在为基于 Java 的文本游戏开发角色生成机制,但我遇到了一个问题,看不出哪里出了问题。我有一个“Character”类,它是抽象的,然后是另一个类“NPCharacter”,它是建立在这个之
抱歉,标题令人困惑。不太确定如何表达它,这可能是问题所在! 我正在寻找一个好的抽象来用于涉及并发线程的情况。 我已经接近了,但还不是很清楚。 稍微简化一下,我在 Android 手机上收集了两种传感器
提前感谢您阅读本文。我不完全理解如何/何时使用摘要,所以我试图在我从事的每个项目中考虑它,看看它是否会在某一天全部点击 Smile | :) 此外,可访问性级别(私有(private)、 protec
我正在探索用于生成 Web 内容的 XML -> XSLT -> HTML 模因。我的 XSLT 经验很少。 我很好奇 XSLT 中有哪些机制可用于处理抽象或“重构”。 例如,使用通用 HTML 和服
在这些谈话中 Nicholas Zakas和 Addy Osmani他们讨论了在构建大型 Javascript 应用程序时将外观模式用作沙箱的想法,以便将应用程序与底层基础库分离。 这种解耦理论上允许
我使用C++和CUDA/C,想为特定问题编写代码,但遇到了一个非常棘手的简化问题。 我在并行编程方面的经验不容忽视,但相当有限,我无法完全预见到此问题的特殊性。 我怀疑是否有一种方便甚至“轻松”的方式
假设我有: trait A class B extends A class C extends A 有没有办法配置类型参数: class Foo[AType <: A with canCreateIn
我是一名优秀的程序员,十分优秀!