0

我正在构建一个“类缓存”,其中包含我想稍后调用的类。

主要目标是我不希望每次需要类实例时都扫描上下文。

# Model / Repository classes

@Getter
@RequiredArgsConstructor
public class Block implements Serializable {
    private final String className;
    private final Set<String> classCandidates = new HashSet<>();
    public boolean addCandidate(final String classCandidate) {
        return this.classCandidates.add(classCandidate);
    }
}

@Slf4j
@Component
@CacheConfig(cacheNames = ConstantsCache.CACHE_BLOCK)
public class BlockRepository {

    @Cacheable(key = "#className")
    public Block findByInputClass(final String className) {
        log.info("---> Loading classes for class '{}'", className);
        val block = new Block(className);
        findCandidates(block);
        return block;
    }
}

首先评估缓存,我将缓存方法@Autowired放在@RestController中,效果很好。当我调用 rest 方法时,缓存被填充。

@RestController
public class Controller {

    @Autowired
    BlockRepository blockRepository;

    @RequestMapping("/findByInputClass")
    public Block findByInputClass(@RequestParam("className") final String className) {
        return blockRepository.findByInputClass(className);
    }
}

之后,我将@Autowired对象移至@Service,创建了一种自行填充缓存的方法。但这不起作用。调用@PostConstructor方法时不会填充缓存。

@Slf4j
@Component
public class BlockCacheService {

    @Autowired
    BlockRepository blockRepository;

    @PostConstruct
    private void postConstruct() {
        log.info("*** {} PostConstruct called.", this.getClass().getTypeName());

        val block = blockRepository.findByInputClass(ConstantsGenerics.BLOCK_PARENT_CLASS);

        final Set<String> inputClasses = getInputFromCandidates(block.getClassCandidates());
        appendClassesToCache(inputClasses);
    }

    private void appendClassesToCache(final Set<String> inputClasses) {
        for (val inputClass : inputClasses) {
            blockRepository.findByInputClass(inputClass);
        }
    }
}

如何使用必须从应用程序开始的服务或组件正确填充缓存。

提前致谢。

编辑:

我在这里找到了一个可能的解决方案:https ://stackoverflow.com/a/28311225/1703546

比我更改了@Service代码以手动放置缓存而不是使用@Cacheable魔术抽象。

现在的课是这样的。

@Slf4j
@Component
public class BlockCacheService {

    @Autowired
    CacheManager cacheManager;

    @Autowired
    BlockRepository blockRepository;

    @PostConstruct
    private void postConstruct() {
        log.info("*** {} PostConstruct called.", this.getClass().getTypeName());

        val block = blockRepository.findByInputClass(ConstantsGenerics.BLOCK_PARENT_CLASS);

        final Set<String> inputClasses = getInputFromCandidates(block.getClassCandidates());
        appendClassesToCache(inputClasses);
    }

    private void appendClassesToCache(final Set<String> inputClasses) {
        for (val inputClass : inputClasses) {
            val block = blockRepository.findByInputClass(inputClass);
            cacheManager.getCache(ConstantsCache.CACHE_BLOCK).put(block.getClassName(), block);
        }
    }
}

现在缓存已正确填充,但问题是,这是最好的解决方案吗?

谢谢。

4

1 回答 1

0

您不能在其中使用方面,@PostConstruct因为它可能尚未创建(顺便记录一下)。

实现这项工作的一种可能方法是实现SmartInitializingBean,因为它在所有单例已完全初始化(包括它们的方面)时提供回调。在您的原始服务上更改它应该可以工作。

话虽如此,您的这段代码对启动时间有影响。你为什么不让你的缓存被懒惰地填充呢?

于 2017-11-05T06:25:01.163 回答