@Cacheable: как передать новый атрибут, который можно использовать в моем собственном генераторе ключей?

Мне нужен ваш опыт :)

Я работаю над приложением, в котором вызовы методов службы должны быть аутентифицированы. Это означает, что я хочу, чтобы каждый вызов метода кэшировался с ключом, содержащим имя пользователя (чтобы неавторизованный пользователь не мог получить информацию, кэшированную авторизованным).

С персонализированным KeyGenerator все работает нормально.

Пример моего ключа: username:USERNAME.appVersion:VERSION.METHOD.PARAM1.etc

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

Пример: appVersion:VERSION.METHOD.PARAM1.etc

Итак, когда я размещаю свои аннотации @Cacheable, есть ли способ установить в нем новый параметр? Генератор ключей сможет перехватить его и узнать, должен ли он добавлять префикс к имени ключа кеша с информацией о пользователе или нет.

Спасибо за вашу помощь :)

Заботиться


person lboix    schedule 20.03.2014    source источник


Ответы (2)


Я не очень понимаю, что вы говорите, говоря «установить в нем новый параметр». Этот параметр должен откуда-то исходить, верно?

KeyGenerator дает вам доступ к Method, фактическому экземпляру и аргументам метода. Вы можете захотеть иметь конкретный KeyGenerator для этой конкретной операции с кэшем, который будет доступен начиная с Spring. 4.1, но в то же время вы можете реализовать композит, который вызывает правильный экземпляр KeyGenerator на основе метода или, например, аннотации, которую вы создали, чтобы пометить его.

person Stephane Nicoll    schedule 20.03.2014

Спасибо snicoll, это было кристально ясно, и вы действительно мне очень помогли :)

В ожидании Spring 4.1 мы с командой решили использовать пользовательскую аннотацию @SharedCache.

Вот несколько примеров кода, которые помогут, если кто-то окажется в такой же ситуации.

  • Учитывая существующий пользовательский GenericKeyGenerator (он создает собственный ключ кеша для каждого вызова кэшированного метода)

  • У нас есть новый пользовательский AuthenticatedGenericKeyGenerator : он унаследован от GenericKeyGenerator и просто добавляет к ключу кеша префикс с информацией о пользователе.

Теперь приложение по умолчанию использует AuthenticatedGenericKeyGenerator:

<cache:annotation-driven key-generator="keyGenerator"/>

<bean id="keyGenerator" class="your.package.AuthenticatedGenericKeyGenerator" />

AuthenticatedGenericKeyGenerator.java в деталях:

public class AuthenticatedGenericKeyGenerator extends GenericKeyGenerator {

    public AuthenticatedGenericKeyGenerator() {

        super(...);
    }

    @Override
    public Object generate(final Object target, final Method method, final Object... params) {

        String cacheKey = super.generate(target, method, params).toString();

        if(!method.isAnnotationPresent(SharedCache.class)) {

            cacheKey =  "user:" + some user information + "." + cacheKey;
        }

        return cacheKey;
    }

}

Наша пользовательская аннотация @SharedCache:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface SharedCache {

}

Теперь нам просто нужно аннотировать методы @Cacheable дополнительным @SharedCache, если мы хотим, чтобы ключ кеша был общим и не был уникальным (например, с идентификатором пользователя).

person lboix    schedule 01.04.2014
comment
Ага, это я и имел в виду, прикольно! Функция, о которой я говорил, теперь доступна в последней версии 4.1.0.BUILD-SNAPSHOT, поэтому, если они связаны только с определенными классами, вы также можете настроить генератор ключей на уровне класса (например, @CacheConfig(keyGenerator = "authGenericKeyGenerator")). - person Stephane Nicoll; 02.04.2014