Spring Boot缓存不基于动态控制器参数缓存方法调用。

huangapple go评论73阅读模式
英文:

Spring Boot cache not caching method call based on dynamic controller parameter

问题

我正在尝试在Spring Boot中使用Caffeine缓存管理器。我已经像这样将一个服务类注入到控制器中:

@RestController
@RequestMapping("property")
public class PropertyController {

    private final PropertyService propertyService;

    @Autowired
    public PropertyController(PropertyService propertyService) {
        this.propertyService = propertyService;
    }

    @PostMapping("get")
    public Property getPropertyByName(@RequestParam("name") String name) {
        return propertyService.get(name);
    }
}

PropertyService看起来像这样:

@CacheConfig(cacheNames = "property")
@Service
public class PropertyServiceImpl implements PropertyService {

    private final PropertyRepository propertyRepository;

    @Autowired
    public PropertyServiceImpl(PropertyRepository propertyRepository) {
        this.propertyRepository = propertyRepository;
    }
    
    @Override
    public Property get(@NonNull String name, @Nullable String entity, @Nullable Long entityId) {
        System.out.println("inside: " + name);
        return propertyRepository.findByNameAndEntityAndEntityId(name, entity, entityId);
    }

    @Cacheable
    @Override
    public Property get(@NonNull String name) {
        return get(name, null, null);
    }
}

现在,当我调用RestController的get端点并提供一个名称值时,每个请求都会在应该被缓存的方法内部执行。

但是,如果我调用控制器的get端点,但将硬编码的字符串传递到服务类方法中,像这样:

@PostMapping("get")
public Property getPropertyByName(@RequestParam("name") String name) {
    return propertyService.get("hardcoded");
}

然后,该方法只在第一次调用时被调用,而在后续调用中不会被调用。

这里发生了什么?为什么在动态提供值时不会缓存方法调用?

以下是一些配置:

@Configuration
public class CacheConfiguration {

    @Bean
    public CacheManager cacheManager() {
        val caffeineCacheManager = new CaffeineCacheManager("property", "another");
        caffeineCacheManager.setCaffeine(caffeineCacheBuilder());
        return caffeineCacheManager;
    }

    public Caffeine<Object, Object> caffeineCacheBuilder() {
        return Caffeine.newBuilder()
                .initialCapacity(200)
                .maximumSize(500)
                .weakKeys()
                .recordStats();
    }
}
英文:

I am attempting to use Spring Boot Cache with a Caffeine cacheManager.

I have injected a service class into a controller like this:

@RestController
@RequestMapping(&quot;property&quot;)
public class PropertyController {

    private final PropertyService propertyService;

    @Autowired
    public PropertyController(PropertyService propertyService) {
        this.propertyService = propertyService;
    }

    @PostMapping(&quot;get&quot;)
    public Property getPropertyByName(@RequestParam(&quot;name&quot;) String name) {
        return propertyService.get(name);
    }
}

and the PropertyService looks like this:

@CacheConfig(cacheNames = &quot;property&quot;)
@Service
public class PropertyServiceImpl implements PropertyService {

    private final PropertyRepository propertyRepository;

    @Autowired
    public PropertyServiceImpl(PropertyRepository propertyRepository) {
        this.propertyRepository = propertyRepository;
    }
    
    @Override
    public Property get(@NonNull String name, @Nullable String entity, @Nullable Long entityId) {
        System.out.println(&quot;inside: &quot; + name);
        return propertyRepository.findByNameAndEntityAndEntityId(name, entity, entityId);
    }

    @Cacheable
    @Override
    public Property get(@NonNull String name) {
        return get(name, null, null);
    }
}

Now, when I call the RestController get endpoint and supply a value for the name, every request ends up doing inside the method that should be getting cached.

However, if I call the controller get endpoint but pass a hardcoded String into the service class method, like this:

@PostMapping(&quot;get&quot;)
public Property getPropertyByName(@RequestParam(&quot;name&quot;) String name) {
    return propertyService.get(&quot;hardcoded&quot;);
}

Then the method is only invoked the first time, but not on subsequent calls.

What's going on here? Why is it not caching the method call when I supply a value dynamically?

Here is some configuration:

@Configuration
public class CacheConfiguration {

    @Bean
    public CacheManager cacheManager() {
        val caffeineCacheManager = new CaffeineCacheManager(&quot;property&quot;, &quot;another&quot;);
        caffeineCacheManager.setCaffeine(caffeineCacheBuilder());
        return caffeineCacheManager;
    }

    public Caffeine&lt;Object, Object&gt; caffeineCacheBuilder() {
        return Caffeine.newBuilder()
                .initialCapacity(200)
                .maximumSize(500)
                .weakKeys()
                .recordStats();
    }
}

答案1

得分: 2

2个解决方案(它们对我有效):

  • 移除.weakKeys()

  • propertyService.get(name.intern()) - 不建议这样做,可能会有很大的成本

抱歉,我没有足够的知识来解释这个。可能与Caffeine的内部键表示有关。

英文:

2 solutions (they work for me):

  • remove .weakKeys()

  • propertyService.get(name.intern()) - wouldn't really do that, possibly a big cost

Sorry, but I don't have enough knowledge to explain this. Probably something to do with internal key representation by Caffeine.

huangapple
  • 本文由 发表于 2020年8月4日 06:42:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/63237889.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定