봄 SpEL을 표현을 사용하여 주석에서 참조 동적 매개 변수를 가져옵니다

eiselems :

내가 뭘하려고하면 @Cacheable 주석 봄처럼 많이 제공 보이는 주석을하는 것입니다.

그것은 다음과 같은 방법 위에 사용하는 :

@CleverCache(key = "'orders_'.concat(#id)")
public Order getOrder(int id) {

내가 캐시 가능을 사용하여 동일한을 사용하면 어떻게 든이 SpEL을 표현을 해석하고 가치있는 키 생성 할 수 있습니다 orders_1234(= 1234 지정된 ID를)

내 일치하는 조언은 다음과 같습니다 :

@Around("CleverCachePointcut(cleverCache)")
public Object clevercache(ProceedingJoinPoint joinPoint, CleverCache cleverCache) throws Throwable {
    String expression = cleverCache.key();
    //FIXME: Please add working code here :D - extracting the key by interpreting the passed SpEL Expression in expression

나는 definitly가 식을 얻을 수 있지만, 아직 그것이 제대로 SpEL을-식 해석되어 작동하게하는 방법을 알아낼하지 않았다.

또 다른 지원 구문은해야 key = "T(com.example.Utils).createCacheKey(#paramOfMethodByName)"키를 만들 수는 A의 정적 도우미가 호출된다.

이 작업을 수있는 방법을 어떤 생각? : 나는에서 조각을 가지고있는 코드에서 확인할 수있다 https://github.com/eiselems/spring-redis-two-layer-cache/blob/master/src/main/java/com/marcuseisele/example/twolayercache/ 의 CleverCache / ExampleAspect.java # L35

어떤 도움도 정말 감사합니다!

kriegaex :

당신이 필요한 컨텍스트 정보가있는 경우, SpEL을 평가하기 위해 실제로 매우 간단합니다. 를 참조하십시오 이 문서 프로그램 SpEL을 구문 분석하는 방법을 찾기 위해.

그 컨텍스트 정보에 관해서는, 당신은 당신이 주석이 방법의 유형에 대해 잘 설명하지 않았다 @CleverCache. 문제는 포인트 컷 도청 모든 방법을 주석하고 각각의 첫 번째 매개 변수는 경우 나도 몰라이다 intID. 이 질문에 대한 대답에 따라 그것은 쉽게 (하나의 간단한 경우) 또는 도청 방법에서 ID 인수 값을 얻기 위해 (단지 정수 ID와 방법을 찾을 경우 - 다른 사람을 위해 당신이 필요로하는) 더 어렵다. 아니면 여러 유형 및 방법 매개 변수, 인스턴스 변수 또는 무엇이든의 이름을 참조하는 식의 모든 종류가 있습니다. 이 솔루션의 복잡성 요구 사항 '복잡성에 연결되어 있습니다. 당신이 더 많은 정보를 제공하는 경우, 어쩌면 나 또한 더 많은 도움을 제공 할 수 있습니다.


업데이트 : 당신의 GitHub의의의 repo 보았다 데, 나는 간단한 경우에 대한 측면을 리팩토링 :

package com.marcuseisele.example.twolayercache.clevercache;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.TimeUnit;

@Aspect
@Component
@Slf4j
public class ExampleAspect {
    private static final ExpressionParser expressionParser = new SpelExpressionParser();

    private Map<String, RedisTemplate> templates;

    public ExampleAspect(Map<String, RedisTemplate> redisTemplateMap) {
        this.templates = redisTemplateMap;
    }

    @Pointcut("@annotation(cleverCache)")
    public void CleverCachePointcut(CleverCache cleverCache) {
    }

    @Around("CleverCachePointcut(cleverCache) && args(id)")
    public Object clevercache(ProceedingJoinPoint joinPoint, CleverCache cleverCache, int id) throws Throwable {
        long ttl = cleverCache.ttl();
        long grace = cleverCache.graceTtl();

        String key = cleverCache.key();
        Expression expression = expressionParser.parseExpression(key);
        EvaluationContext context = new StandardEvaluationContext();
        context.setVariable("id", id);
        String cacheKey = (String) expression.getValue(context);
        System.out.println("### Cache key: " + cacheKey);

        long start = System.currentTimeMillis();
        RedisTemplate redisTemplate = templates.get(cleverCache.redisTemplate());
        Object result;
        if (redisTemplate.hasKey(cacheKey)) {
            result = redisTemplate.opsForValue().get(cacheKey);
            log.info("Reading from cache ..." + result.toString());

            if (redisTemplate.getExpire(cacheKey, TimeUnit.MINUTES) < grace) {
                log.info("Entry is in Grace period - trying to refresh it");
                try {
                    result = joinPoint.proceed();
                    redisTemplate.opsForValue().set(cacheKey, result, grace+ttl, TimeUnit.MINUTES);
                    log.info("Fetch was successful - new value will be returned");
                } catch (Exception e) {
                    log.warn("An error occured while trying to refresh the value - extending the old one", e);
                    //TODO: think about only adding 5 minutes on top of grace, or 50% of ttl on top of grace
                    //if protected by a circuit breaker we could go REALLY low here
                    redisTemplate.opsForValue().getOperations().expire(cacheKey, grace+ttl, TimeUnit.MINUTES);
                }

            }

        } else {
            result = joinPoint.proceed();
            log.info("Giving from method ..." + result.toString());
            redisTemplate.opsForValue().set(cacheKey, result, ttl + grace, TimeUnit.MINUTES);
        }

        long executionTime = System.currentTimeMillis() - start;
        log.info("{} executed in {} ms", joinPoint.getSignature(), executionTime);
        log.info("Result: {}", result);
        return result;
    }
}

은 diff는 다음과 같습니다 :

DIFF 스크린 샷

추천

출처http://43.154.161.224:23101/article/api/json?id=208942&siteId=1