Динамически определять информацию о методе из тела лямбда-выражения в Java - PullRequest
0 голосов
/ 01 февраля 2019

Я пытаюсь написать простой механизм кэширования на Java.Он должен кэшировать вызовы веб-службы и результаты.Использование должно быть максимально простым.Поэтому я хотел бы использовать лямбда-выражения, подобные следующему примеру:

// normal call without caching
Result result1 = service.callMethodA("Parameter1");

// call with cache
Result result2 = Cache.executeWithCache(() -> service.callMethodA("Parameter1"));

Моя проблема здесь в том, что Мне нужно вычислить ключ кэша для вызова на основе заданного

  • тип сервиса (получить имя типа из экземпляра объекта)
  • метод сервиса (получить имя вызываемого метода)
  • параметры (массив с типом и значением)

Но я не смог получить эту информацию в Java из тела лямбда-выражения.Я пытался использовать Supplier<T> в executeWithCache методе, но кажется, что это невозможно.

Единственный способ предоставить эту информацию, который я нашел, - это установить непосредственно в вызове.Но это не очень удобно.Как:

Result result = Cache.executeWithCache(service, "callMethodA", new Object[] {"Parameter1"});

У кого-нибудь есть идея получить эту информацию из лямбда-звонка?

Спасибо Томасу


ПРИМЕЧАНИЕ:

Я реализовал это с помощью C # в одном из моих других приложений.Там я использую дженерики и MethodCallExpression, который прекрасно работает:

public ServiceDataCacheResult<T> ExecuteWithCache<T>(Expression<Func<T>> serviceMethodExpression)
{
    ThrowIfDisposed();

    var methodExpression = serviceMethodExpression.Body as MethodCallExpression;
    if (methodExpression == null)
    {
        throw new NotSupportedException(
            "Only Expressions with body of type MethodCallExpression are supported!");
    }

    var cacheKey = GenerateCacheKey(methodExpression.Method, methodExpression.Arguments);

    if (_cacheStore.Contains(cacheKey))
    {
        var existingCacheValue = (ServiceDataCacheItem<T>) _cacheStore.Get(cacheKey);

        // Check for equality too because hashing can have collisions
        if (EqualExpressions(existingCacheValue.Expression, methodExpression))
        {
            return new ServiceDataCacheResult<T>
            {
                Value = existingCacheValue.Value,
                CacheKey = cacheKey,
                CreatedTime = existingCacheValue.CreatedTime,
                ExpirationTime = existingCacheValue.ExpirationTime,
                GotFromCache = true,
                StoredToCache = false
            };
        }
    }

    // compile and execute method
    var result = serviceMethodExpression.Compile()();

    var createdTime = DateTime.Now;
    var expireTime = createdTime.Add(ItemLifeTime);

    var newCacheValue = new ServiceDataCacheItem<T>
    {
        Value = result,
        Expression = methodExpression,
        CreatedTime = createdTime,
        ExpirationTime = expireTime
    };

    _cacheStore.Add(cacheKey, newCacheValue, new CacheItemPolicy
    {
        AbsoluteExpiration = expireTime
    });

    return new ServiceDataCacheResult<T>
    {
        Value = result,
        CacheKey = cacheKey,
        CreatedTime = newCacheValue.CreatedTime,
        ExpirationTime = newCacheValue.ExpirationTime,
        GotFromCache = false,
        StoredToCache = true
    };
}

Позвоните через:

ServiceDataCacheResult<Result> result = Cache.ExecuteWithCache(() => service.CallMethodA("Parameter1"));
...