当前位置: 首页 > 知识库问答 >
问题:

如何防止在spring cacheable中更改缓存返回值

费凯康
2023-03-14

我正在研究Spring3.1注释缓存,ehcache作为缓存实现。

一个返回值像这样的方法

@Cacheable("cache")
public MyObject getObj(Object param);

我第一次得到了一个myject返回值,它是可编辑的。ehache可以通过设置“拷贝读取”或“拷贝写入”来做些什么。它将强制序列化读/写对象。但是在第一次Spring不会从缓存中获取值,它总是返回通过方法本身。

是否有某种方法可以获取只读返回值?

共有3个答案

松亦
2023-03-14

通过创建另一个类,它包含返回对象的相同属性,然后我使用ModelMapper将返回的对象映射到我的新对象。例如,我有一个类MyObject:

    public class MyObject {
     private Long id;
     private Long label;

    //getters and setters
    }

新创建的类:

public class MyObjectCopy {
    private Long id;
    private Long label;

    //getters and setters
}

和返回MyObject的可缓存方法:

 @Cacheable("cache")
public MyObject getMyObject();

为了防止修改缓存:我必须将该对象映射到我的类副本,然后处理它:

MyObjectCopy myObjectCopy = modelMapper.map(myobject, MyObjectCopy.class);

不要忘记为嵌套对象创建一个复制类;

子车新立
2023-03-14

我对Spring缓存也有同样的问题。我不想从缓存中接收相同的java对象。

在我的例子中,我希望缓存具有许多字段的大型java对象等等。因此,使用深度复制复制所有数据类是非常痛苦的。我读了关于使用序列化复制java对象的文章。

http://www.javaworld.com/article/2077578/learn-java/java-tip-76--an-alternative-to-the-deep-copy-technique.html

这让我想到了只缓存序列化数据的想法。每次从缓存中读取对象时,都会反序列化该对象。

对于序列化,我使用了apache共享助手方法

@Override
public SerializedQuestions readUserQuestion(UID questionId, Locale locale) {
 byte[] serializedData = readCachedUserQuestion(questionId, locale);
 Object deserializedobject = org.apache.commons.lang.SerializationUtils.deserialize(serializedData);
 return (SerializedQuestions) deserialize;
}

@Override
@Cacheable(value = SpringCacheKeys.USER_QUESTION_CACHE)
  public byte[] readCachedUserQuestion(UID questionId, Locale locale) {

  //read object from db
  SerializedQuestions questions = new SerializedQuestions()

  return org.apache.commons.lang.SerializationUtils.serialize(questions);
}

如果对readCachedUserQuestion的调用可能在同一个类中,这取决于spring配置。默认情况下,只缓存对方法的外部调用。

严高峻
2023-03-14

您可以编写自己的方面,始终创建返回值的副本,这将使您独立于某些Ehcache设置。

首先,像@CopyResnValue这样的标记注释很适合表达切入点:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface CopyReturnValue {
}

现在,方面可以将此注释用于切入点表达式:

@Aspect
@Component
public class CopyReturnValueAspect {
    @Around("@annotation(CopyReturnValue)")
    public Object doCopyReturnValue(ProceedingJoinPoint pjp) throws Throwable {
        Object retVal = pjp.proceed();
        Object copy = BeanUtils.cloneBean(retVal); // create a copy in some way
        return copy;
    }
}

最后,将注释添加到方法中:

@CopyReturnValue
@Cacheable("cache")
public MyObject getObj(Object param);

对于CopyReturnValueAspect,我使用BeanUtils创建返回值的副本,这只是一个示例。有关该主题的更多信息,您可能希望了解如何将属性从一个JavaBean复制到另一个JavaBean?

哦,如果您还没有在Spring配置中启用@AspectJ支持,请不要忘记:

<aop:aspectj-autoproxy />
 类似资料:
  • 问题内容: 我已经编写了一个Linux驱动程序,该驱动程序ioremaps将特定设备的PCI BAR0导出为sysfs二进制属性,允许用户空间直接控制它。 当我尝试在属性顶部使用MMAP来直接访问该位内存(从Userland程序)时,问题就浮现了。读取可以很好地完成并返回期望值,尽管当我写入该内存时,它似乎被缓存在内核和内存之间的某个地方,而不是传递给GM​​CH根联合体(以及设备)。我想做的是每

  • 问题内容: 我有一个简单的html: 在test.js中,我更改了Javascript函数,但是我的浏览器正在缓存该文件。如何禁用脚本src的缓存? 问题答案: 将随机查询字符串添加到 您可以通过在每次更改时增加查询字符串来手动执行此操作: 或者,如果您使用服务器端语言,则可以自动生成以下内容: ASP.NET:

  • 我正在MAMP中开发一个单页Javascript应用程序。我的JavaScript和超文本标记语言模板文件在请求之间被缓存。 有没有一种简单的方法可以在MAMP中指出我想要阻止http文件缓存?可能使用文件?我应该把或修改Mac上MAMP的虚拟主机?

  • 我目前使用service/$resource进行ajax调用(在本例中是GET),IE缓存调用,以便无法从服务器检索新的数据。我使用了一种通过谷歌搜索找到的技术来创建一个随机数并将其附加到请求中,这样IE就不会为数据进行缓存。 还有比在每个请求中添加cacheKill更好的方法吗?

  • 我发现了与jQuery相关的类似问题。我的目标是找出如何防止jQueryMobile和PhoneGap中的缓存(我使用JSONP)。我正在进行一些ajax调用,动态地填充listview。我想在每次初始化页面(pageinit)时查询web服务。在我的android设备上,在新的查询之后,每次我进入页面时,数据都会添加到listview中。它不会删除,每次我访问页面时,我都会添加一个副本。我认为这

  • 我有一个Dockerfile文件,试图将一个web应用程序打包并部署到一个容器中。在Docker映像构建期间,app的代码从git存储库中获取。以下是Dockerfile快照: 我希望 docker 不要缓存 RUN git 克隆的步骤 -- 以便存储库上正在进行的更新可以反映在 Docker 映像构建中。有可能做到这一点吗?