Spring Cache для отключения кеша по конфигурации cacheName

Я использую весеннюю загрузку, и очень легко интегрировать весенний кеш с другим компонентом кеша.

Кэшируя данные, мы можем использовать аннотацию @Cachable, но все же нам нужно настроить и добавить cacheName в cacheManager, без этого шага мы получим исключение при доступе к методу:

java.lang.IllegalArgumentException: Cannot find cache named 'xxxx' for Builder

У меня вопрос, можно ли отключить кеш вместо того, чтобы поднимать ошибку, если мы не настроим cacheName? Я поднял это, потому что кеш Spring предоставляет конфигурацию spring.cache.cacheNames в CacheProperties.

Не уверен, что атрибут condition в @Cachable работает для этого.

Любая идея ценится!! Заранее спасибо!


person Colin Zhang    schedule 15.09.2018    source источник


Ответы (1)


Это действительно зависит от вашего «поставщика кэширования» и реализации CacheManager, в частности. Начиная с абстракции кэша в Spring это просто «абстракция», она позволяет вам подключать различных поставщиков и серверные хранилища данных для поддержки кэшей, необходимых вашему приложению (т.е. как определено аннотациями кэширования Spring или, альтернативно, аннотациями JSR-107-JCache; см. href="https://docs.spring.io/spring/docs/current/spring-framework-reference/integration.html#cache-jsr-107-summary" rel="nofollow noreferrer">здесь) .

В настоящее время нет возможности отключить эту проверку инициализации (т. е. генерировать исключение) для несуществующих кешей. Лучшее, что вы можете сделать, это, подобно реализации ConcurrentMapCacheManager, лениво создать Caches. Однако это сильно зависит от реализации вашего поставщика кэширования. Очевидно, что некоторые провайдеры кэширования более сложны, чем другие, и создание Cache на лету (то есть лениво), возможно, дороже и затратнее, поэтому провайдер кэширования не поддерживает его или не рекомендует.

Тем не менее, вы можете обойти это ограничение, обернув любую реализацию CacheManager (по вашему выбору) и делегировав базовой реализации «существующую» Caches и «безопасно» обработав «несуществующую» Caches, рассматривая ее как промах кеша, просто предоставление некоторых простых реализаций оболочки основных интерфейсов Spring CacheManager и Cache.

Вот пример интеграционного тестового класса, который демонстрирует вашу текущую проблему. Обратите внимание на тест/утверждения для несуществующего Caches.

Затем, вот пример тестового класса интеграции, который демонстрирует, как эффективно отключить кэширование для несуществующего Caches (не предоставляется поставщиком кэширования). Еще раз обратите внимание на test/assertions для безопасного доступа к несуществующему Caches.

Это стало возможным благодаря делегат-оболочка для CacheManager (который упаковывает и делегирует существующему провайдеру кэширования, который в данном случае снова является просто ConcurrentMapCacheManager (см. здесь), но будет работать для любого провайдера кэширования, поддерживаемого Spring Cache Abstraction) вместе с NoOpNamedCache реализация интерфейса Spring Cache. Этот нерабочий экземпляр Cache может быть Singleton и повторно использоваться для всех несуществующих Caches, если вас не волнует имя. Но это дало бы вам степень видимости, в которой «именованные» Caches не настроены с фактическим Cache, поскольку это, скорее всего, повлияет на ваши службы (т.е. методы службы без включенного кэширования, потому что «именованный» кеш не существует ).

В любом случае, это может быть не совсем то, что вам нужно, и я бы даже предостерег вас проявлять особую осторожность, если вы запускаете это в производство, поскольку (я бы сказал) это действительно должно быстро выйти из строя из-за отсутствия Caches, но это действительно достигает того, что вы хочу.

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

Надеюсь, это даст вам некоторые идеи.

Спасибо за ваше объяснение. Мне просто интересно, что делает конфигурацию избыточной. Теперь я знаю, что я могу сделать.

person John Blum    schedule 17.09.2018
comment
Фантастика, вот что я в итоге сделал. Жаль, что Spring не позволяет это настроить или просто предупреждает об отсутствии кеша вместо того, чтобы все взрывать. Я думаю о сценарии, в котором вы в конечном итоге вызываете аннотированную службу @Cachable во время выполнения, но не имеете кеша, определенного для этого ключа. В любом случае это решение работает для этого случая. - person Colin Zhang; 19.09.2018
comment
Например, если вы будете использовать предоставленный Spring Framework _1_ (не рекомендуется для производства, за исключением действительно простых UC), то, если вы решите не объявлять свои кэши во время настройки/инициализации (используя по умолчанию, нет- конструктор arg), то "_2_" создаются лениво. Однако, если вы объявите свой «_3_» во время настройки/инициализации (используя конструктор, принимающий аргументы имени кэша), то, если ваше приложение использует кэш (например, _4_), не объявленный явно, тогда будет выдано исключение, поскольку _5_ вернет _6_, а логика инициализации _7_ будет бросьте _8_, если _9_ недоступно для операции кэширования (следуйте из _10 _ вниз, здесь, здесь, здесь , здесь, а затем здесь). - person Stefan; 09.02.2020