You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring缓存:如何在@Cacheable的unless中引用局部布尔变量?

解决@Cacheable中unless无法引用局部布尔变量的问题

你遇到的核心问题是:@Cacheable注解的SpEL表达式无法直接访问方法内部的局部变量,因为注解的SpEL解析时机在方法执行前后,局部变量仅在方法运行时存在,不在SpEL的可访问上下文里。下面给你两种可行的解决方案:

方案一:将判断标志存入返回对象

最直接的方式是给返回的Book类添加一个用于标记是否为部分数据的属性,然后在unless中通过返回值(#result)访问这个属性。

步骤1:修改Book类,添加标志属性

public class Book {
    private String title;
    // 原有其他属性...
    private boolean missingPages; // 新增标记属性

    // 新增getter和setter
    public boolean isMissingPages() {
        return missingPages;
    }

    public void setMissingPages(boolean missingPages) {
        this.missingPages = missingPages;
    }

    // 原有getter/setter...
}

步骤2:修改方法逻辑,设置标志并更新注解

@Cacheable(cacheNames="book", unless="#result.isMissingPages")
public Book findBook(String name) {
    Book book = bookShelf.get(name);

    boolean isMissingPages = checkMissingPages(book);
    if (isMissingPages) {
        book.setTitle(book.getTitle() + " Missing Pages!");
        book.setMissingPages(true); // 标记为部分数据
    } else {
        book.setMissingPages(false); // 标记为完整数据(也可默认false,显式设置更清晰)
    }

    return book;
}

方案二:使用包装类封装结果(不修改原有Book类)

如果不想改动Book类,可以创建一个包装类,同时保存Book对象和判断标志,然后在unless中判断包装类的标志:

步骤1:创建包装类

public class BookResult {
    private Book book;
    private boolean isPartialData;

    // 构造器、getter
    public BookResult(Book book, boolean isPartialData) {
        this.book = book;
        this.isPartialData = isPartialData;
    }

    public Book getBook() {
        return book;
    }

    public boolean isPartialData() {
        return isPartialData;
    }
}

步骤2:修改方法返回类型和逻辑

@Cacheable(cacheNames="book", unless="#result.isPartialData")
public BookResult findBook(String name) {
    Book book = bookShelf.get(name);

    boolean isMissingPages = checkMissingPages(book);
    if (isMissingPages) {
        book.setTitle(book.getTitle() + " Missing Pages!");
    }

    return new BookResult(book, isMissingPages);
}

补充说明:为什么原写法无效

你之前用的#root.target.isMissingPages是试图访问目标类的成员变量,但你代码里的isMissingPages是方法内部的局部变量,不属于类的成员,所以SpEL根本找不到这个变量,自然不会生效。

SpEL在@Cacheable注解中能访问的常用变量包括:

  • #result:方法的返回值
  • #args:方法的参数数组
  • #p0/#a0:方法的第一个参数(以此类推#p1/#a1对应第二个参数)
  • #root.target:当前被调用的目标对象
  • #root.method:当前被调用的方法

内容的提问来源于stack exchange,提问作者Alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 23:11:15