首页 > 解决方案 > SpelEvaluationException:试图在空上下文对象上调用方法

问题描述

我正在尝试做一个简单的缓存任务。我有一个Holiday对象,它有两个字段:referenceDateisHoliday. 然后,我有一个方法可以向 rest api 发出 HTTP 请求,以检查日期是否为假期。我想要实现的是:如果当前缓存Holiday的对象与作为参数传递的对象具有相同的referenceDate,则返回缓存的值。我有一个特定的类来执行该检查。这是代码:

假期班

@AllArgsConstructor
@Getter
public class Holiday {
    public LocalDate referenceDate;
    public boolean isHoliday;
}

缓存服务类

@DomainService
public class CacheService {

    @Autowired
    private CacheManager cacheManager;

    public boolean isReferenceDateCached(final LocalDate referenceDate){
        final Holiday holiday = (Holiday) cacheManager.getCache("holiday").get("holidaycheck");
        return(holiday.getReferenceDate().equals(referenceDate));
    }
}

HolidatInfraService 类

@AllArgsConstructor
@Service
@Slf4j
public class HolidayInfraService {

    @Autowired
    private final CacheService cacheService;

    @Cacheable(value = "holiday", key = "holidaycheck", condition = "#cacheService.isReferenceDateCached(#holidayDateToCheck)")
    public Holiday isHoliday(final LocalDate holidayDateToCheck) {
        //some code to call a rest api
    }

}

这是我在尝试时从单元测试中得到的错误holidayInfraService.isHoliday(someDate)

org.springframework.expression.spel.SpelEvaluationException: EL1011E: Method call: Attempted to call method isReferenceDateCached(java.time.LocalDate) on null context object

从这个异常消息似乎很明显,它cacheService是空的。但是,当我调试代码并进入内部isHoliday时,cacheService它不为空。也许注释运行时它还没有自动装配?这也是我第一次与 SPEL 合作,所以也许那里也有一些东西。如果实际上cacheService还没有自动装配,有没有解决方法?

标签: springspring-bootjava-11spring-el

解决方案


因为您正在使用@Cacheable(...)注释,所以 Spring 将使用 context class 评估该 SpEL 表达式MethodBasedEvaluationContext。这会将根对象设置为 a CacheExpressionRootObject,并且将使用该根对象执行属性查找。

由于您试图引用 bean 上的属性,因此最简单的解决方案是直接在 SpEL 表达式中引用该 bean。这是通过@(例如@myBeanName)完成的。然后 Spring 将在ApplicationContext. 请记住,没有明确名称定义的 bean 将使用类名的较低驼峰式命名。例如,名称为 的类MyBeanName的 bean 名称为myBeanName.

尝试将您的condition=块更改为

@Cacheable(value = "holiday", key = "holidaycheck", condition = "@cacheService.isReferenceDateCached(#holidayDateToCheck)")
public Holiday isHoliday(final LocalDate holidayDateToCheck) {
    //some code to call a rest api
}

推荐阅读