简体   繁体   English

Infinispan + Spring 启动 - 不缓存

[英]Infinispan + Spring Boot - Doesn't Cache

Trying to Implement infinispan base cache on spring boot using custom annotation:尝试使用自定义注释在 spring 引导上实现 infinispan 基本缓存:

@Aspect
@Configuration
@Slf4j
public class CacheAnnotationAspect {
    Logger logger = LoggerFactory.getLogger(CacheAnnotationAspect.class);

    @Autowired
    InfinispanCacheService cacheService;

    @Around("@annotation(com.calsoft.lib.cache.CacheResult)")
    public Object cacheResult(ProceedingJoinPoint joinPoint)throws Throwable{
        logger.info("Cache Operation :: CacheResult annotation advice invoked...");
        CacheResult cacheResult=(CacheResult) getAnnotation(joinPoint,CacheResult.class);
        CacheConfig cacheConfig=CacheConfig.from(cacheResult);
        Object resultFromCache=getFromCache(joinPoint,cacheConfig);
        if(resultFromCache!= null){
            return resultFromCache;
        }
        Object result=joinPoint.proceed(joinPoint.getArgs());
        storeInCache(result,joinPoint,cacheConfig);
        return result;
    }

    private void storeInCache(Object result, ProceedingJoinPoint joinPoint, CacheConfig cacheConfig) {
        if(result==null){
            log.info("Cache op :: null values not cached");
            return;
        }
        CacheService cacheService=getCacheService();
        if(cacheService==null){
            logger.info("Cache op :: CacheGet Failed : No CacheService available for use..");
        }
        DefaultCacheKey defaultCacheKey=getKey(joinPoint,cacheConfig);
        String cacheName=getCacheName(cacheConfig.getCacheName(),joinPoint);
        long lifeSpan=cacheConfig.getLifespan();
        if(lifeSpan== CommonConstant.CACHE_DEFAULT_LIFE){
            cacheService.put(cacheName,defaultCacheKey,result);
        }else{
            cacheService.put(cacheName,defaultCacheKey,result,lifeSpan,cacheConfig.getUnit());
        }
        logger.info("Cache Op :: Result cached :: {} ",cacheConfig);
    }

    private DefaultCacheKey getKey(ProceedingJoinPoint joinPoint, CacheConfig cacheConfig) {
        List<Object> keys=new ArrayList<>();
        Object target=joinPoint.getTarget();
        MethodSignature methodSignature=MethodSignature.class.cast(joinPoint.getSignature());
        Method method=methodSignature.getMethod();
        Annotation[][] parameterAnnotations=method.getParameterAnnotations();
        if(isEmpty(trim(cacheConfig.getKeyPrefix()))){
            keys.add(target.getClass().getName());
            keys.add(method.getName());
        }else{
            keys.add(cacheConfig.getKeyPrefix());
        }
        if(isCacheKeySpecified(parameterAnnotations)){
            keys.addAll(getCacheKeys(joinPoint,parameterAnnotations));
        }else{
            keys.addAll(Arrays.asList(joinPoint.getArgs()));
        }
        return new DefaultCacheKey(keys.toArray());
    }

    private Collection<?> getCacheKeys(ProceedingJoinPoint joinPoint, Annotation[][] parameterAnnotations) {
    Object[] args=joinPoint.getArgs();
    List<Object> result=new ArrayList<>();
    int i=0;
    for(Annotation[] annotations: parameterAnnotations){
        for(Annotation annotation: annotations){
            if(annotation instanceof CacheKey){
                result.add(args[i]);
                break;
            }
        }
        i++;
    }
    return result;
    }

    private boolean isCacheKeySpecified(Annotation[][] parameterAnnotations) {
        for(Annotation[] annotations:parameterAnnotations){
            for(Annotation annotation:annotations){
               if(annotation instanceof CacheKey) {
                return true;
               }
            }
        }
        return false;
    }

    private Object getFromCache(ProceedingJoinPoint joinPoint, CacheConfig cacheConfig) {
        CacheService cacheService = getCacheService();
        if (cacheService == null) {
            logger.info("Cache op :: CacheGet Failed : No CacheService available for use..");
        }
        String cacheName=getCacheName(cacheConfig.getCacheName(),joinPoint);
        DefaultCacheKey defaultCacheKey=getKey(joinPoint,cacheConfig);

        return cacheService.get(cacheName,defaultCacheKey);
    }

    private String getCacheName(String cacheName, ProceedingJoinPoint joinPoint) {
        boolean nameNotDefined=isEmpty(trim(cacheName));
        if(nameNotDefined){
            logger.error("Cache op :: Cache Name not defined");
        }else{
            CacheService cacheService=getCacheService();
            if(!cacheService.cacheExists(cacheName)){
                throw new RuntimeException("Cache with the name "+ cacheName+" does not exists");
            }
        }
        return cacheName;
    }

    private CacheService getCacheService() {
        return cacheService;
    }

    private Annotation getAnnotation(ProceedingJoinPoint joinPoint, Class type) {
        MethodSignature methodSignature=MethodSignature.class.cast(joinPoint.getSignature());
        Method method=methodSignature.getMethod();
        return method.getAnnotation(type);
    }

}

Above class << CacheAnnotationAspect >> is custom annotation @CacheResult Aspect implementation where it will first try to retrieve from cache and if not found will make actual dao call and then store in cache.上面的 class << CacheAnnotationAspect >> 是自定义注释 @CacheResult Aspect 实现,它将首先尝试从缓存中检索,如果没有找到将进行实际的 dao 调用,然后存储在缓存中。

Below is the of the implementation of InfinispanCacheService which invokes cachemager to get/put cache entries.下面是 InfinispanCacheService 的实现,它调用 cachemager 来获取/放置缓存条目。

@Service
public class InfinispanCacheService implements CacheService {

    Logger logger = LoggerFactory.getLogger(InfinispanCacheService.class);
    @Autowired
    private DefaultCacheManagerWrapper cacheManagerWrapper;
    private DefaultCacheManager infiniCacheManager;

    private DefaultCacheManager initializeCacheManager(){
        if(infiniCacheManager==null){
            infiniCacheManager=cacheManagerWrapper.getCacheManager();
        }
        return infiniCacheManager;
    }
    @PostConstruct
    public void start(){
        logger.info("Initializing...InifinispanCacheService ....");
        initializeCacheManager();
        for(String cacheName : infiniCacheManager.getCacheNames()){
            infiniCacheManager.startCache(cacheName);
        }
    }
    @Override
    public Object get(String cacheName, Object key) {
        return getCache(cacheName).get(key);
    }

    @Override
    public void put(String cacheName, Object key, Object value, long lifespan, TimeUnit unit) {
        Cache cache=getCache(cacheName);
        cache.put(key,value,lifespan,unit);
    }

    @Override
    public void put(String cacheName, Object key, Object value) {
        Cache cache=getCache(cacheName);
        cache.put(key,value);
    }

    private Cache<Object,Object> getCache(String cacheName) {
        Cache<Object,Object> cache;
        if(isEmpty(trim(cacheName))){
            cache=infiniCacheManager.getCache();
        }else{
            cache=infiniCacheManager.getCache(cacheName,false);
        }
        return cache;
    }

    @Override
    public boolean cacheExists(String cacheName) {
        return infiniCacheManager.cacheExists(cacheName);
    }
}

<<<<<< The DefaultCacheManager below is one which during startup initializes the DefaultCacheManager by loading the infispan.xml configuration >>>>> <<<<<< 下面的DefaultCacheManager 是一个在启动过程中通过加载infispan.xml 配置来初始化DefaultCacheManager >>>>>

@Component
public class DefaultCacheManagerWrapper {

    Logger logger = LoggerFactory.getLogger(DefaultCacheManagerWrapper.class);
//    @Value("${classpath:spring.cache.infinispan.config}")
    private String fileName="file:\\calsoft\\devlabs\\ecom2\\ecom-svc-admin\\src\\main\\resources\\infinispan.xml";
    private DefaultCacheManager infiniCacheManager;

    @PostConstruct
    public void start(){
        logger.info(" Received File Name :: {} ",fileName);
        try{
            URL fileUrl=new URL(fileName);
            URLConnection urlConnection=fileUrl.openConnection();
            InputStream inputStream=urlConnection.getInputStream();
            infiniCacheManager=new DefaultCacheManager(inputStream);
            infiniCacheManager.start();
            logger.info("Cache Manager Initialized....");
        }catch(MalformedURLException mue){
            logger.error("Error creating file url ",mue.getMessage());
        } catch (IOException e) {
            logger.error("Error creating file url ",e.getMessage());
        }
    }
    public void stop() { infiniCacheManager.stop();}
    public DefaultCacheManager getCacheManager(){
        return infiniCacheManager;
    }
}

<<<< Infinispan.xml configuration >> <<<< Infinispan.xml配置>>

   <?xml version="1.0" encoding="UTF-8"?>
<infinispan xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:scehmaLocation="
            urn:infinispan:config:7.2
            http://www.infinispan.org/schemas/infinispan-config-7.2.xsd"
            xmlns="urn:infinispan:config:7.2">
    <cache-container default-cache="attributeset-cache">
        <!-- template configurations -->
        <local-cache-configuration name="local-template">
            <expiration interval="10000" lifespan="50000" max-idle="50000"/>
        </local-cache-configuration>

        <!-- cache definitions -->
        <local-cache name="attributeset-cache" configuration="local-template"/>
    </cache-container>
</infinispan>

Annotation at controller level: controller 级别的注释:

@CacheResult(cacheName= CommonConstant.ATTRIBUTE_SET_CACHE,lifespan=10,unit = TimeUnit.MINUTES)
    @GetMapping("/eavattributeset")
    public List<EavAttributeSet> fetchAllAttributes() {
            return eavAttributeService.fetchAllEavattributesets();
    }

<< EavAttributeService >> << EavAttributeService >>

@Service
public class EavAttributeService {

    Logger logger = LoggerFactory.getLogger(EavAttributeService.class);
    @Autowired
    private EavAttributeJpaRepository eavAttributeJpaRepository;

    @Autowired
    EavAttributeSetJpaRepository eavAttributeSetJpaRepository;  

    public List<EavAttributeSet> fetchAllEavattributesets() {

        return eavAttributeSetJpaRepository.findAll();

    }
}

<< CacheConfig >> <<缓存配置>>

@Data
@Slf4j
@AllArgsConstructor
@NoArgsConstructor
public class CacheConfig {
    private String cacheName;
    private long lifespan;
    private TimeUnit unit;
    private String keyPrefix;

    public static CacheConfig from(CacheResult cacheResult) {
        return new CacheConfig(cacheResult.cacheName(), cacheResult.lifespan(), cacheResult.unit(), cacheResult.keyPrefix());
    }

}

Issue: The data is not getting cache, Wherever @CacheResult annotation is used the CacheAnnotationAspect is getting invoked and the check for data also happens in cache but when it tries to store the data in cache it does not cache and every subsequent call of this method does not return any data.问题:数据没有得到缓存,无论在哪里使用 @CacheResult 注释,都会调用 CacheAnnotationAspect 并且数据检查也在缓存中发生,但是当它尝试将数据存储在缓存中时,它不会缓存并且每次后续调用此方法不返回任何数据。

It works fine when i try with below configuration on infinispan.xml.当我在 infinispan.xml 上尝试以下配置时,它工作正常。

<expiration lifespan="50000"/>

Can you try with the above config and see if it using the cached data.您可以尝试使用上述配置并查看它是否使用缓存的数据。

I guess it could be the max-idle timeout (10 milliseconds) which could be issue.我想这可能是最大空闲超时(10毫秒)可能是问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM