Um guia para armazenamento em cache na primavera
1. A abstração do cache?
Neste artigo, vamos mostrar comouse the Caching Abstraction in Spring - e, de modo geral, melhorar o desempenho do seu sistema.
Ativaremos o cache simples para alguns exemplos de métodos do mundo real e discutiremos como podemos melhorar de forma prática o desempenho dessas chamadas por meio do gerenciamento inteligente de cache.
Leitura adicional:
Exemplo de Ehcache de inicialização de primavera
Um guia rápido e prático para usar o Spring com Ehcache.
Despejo de cache na inicialização do Spring
Aprenda como invalidar caches com o Spring Boot.
2. Começando
A abstração de cache de núcleo fornecida pelo Spring reside no smodulespring-context . Portanto, ao usar o Maven, nossopom.xml deve conter a seguinte dependência:
org.springframework
spring-context
5.1.8.RELEASE
Curiosamente, há outro módulo denominadospring-context-support, que fica no topo dospring-context module e fornece mais algunsCacheManagers apoiado porEhCache ouCaffeine. Se você for usá-los como armazenamento em cache, use ospring-context-support module em vez disso:
org.springframework
spring-context-support
5.1.8.RELEASE
Como o módulospring-context-support depende transitivamente dospring-context module, não há necessidade de uma declaração de dependência separada para ospring-context.
2.1. Spring Boot
Se você for um usuário Spring Boot, use o pacotespring-boot-starter-cache starter para adicionar facilmente as dependências de cache:
org.springframework.boot
spring-boot-starter-cache
Sob o capô, o starter traz o smodulespring-context-support .
3. Ativar cache
Para habilitar o armazenamento em cache, o Spring faz bom uso de anotações, como ativar qualquer outro recurso de nível de configuração na estrutura.
O recurso de cache pode ser habilitado declarativamente, simplesmente adicionando a anotação@EnableCaching a qualquer uma das classes de configuração:
@Configuration
@EnableCaching
public class CachingConfig {
@Bean
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager("addresses");
}
}
Você pode, é claro, a configuração deenable cache management with XML também:
Note: Depois de habilitar o cache - para a configuração mínima - nósmust registramos acacheManager.
Using XML does enable more flexible options para configurar o cache - você pode especificar seu próprio Cache-Manager, Cache-Resolver, Error-Handler e, geralmente, usar opções de personalização mais avançadas (refer to the Javadoc para mais detalhes).
3.1. Spring Boot
Ao usar o Spring Boot, a mera presença do pacote inicial no caminho de classe junto com aEnableCaching annotation registraria o mesmoConcurrentMapCacheManager. So, não há necessidade de uma declaração de bean separada.
Além disso, podemos personalizar oauto-configuredCacheManager using um ou maisCacheManagerCustomizer<T> beans:
@Component
public class SimpleCacheCustomizer
implements CacheManagerCustomizer {
@Override
public void customize(ConcurrentMapCacheManager cacheManager) {
cacheManager.setCacheNames(asList("users", "transactions"));
}
}
A configuraçãoCacheAutoConfiguration auto seleciona esses personalizadores e os aplica aoCacheManager atual antes de sua inicialização completa.
4. Use Cache com Anotações
Depois de ativar o cache, a próxima etapa é vincular o comportamento do cache aos métodos com anotações declarativas.
4.1. @Cacheable
A maneira mais simples de habilitar o comportamento de cache de um método é demarcá-lo com@Cacheablee parametrizá-lo com o nome do cache onde os resultados seriam armazenados:
@Cacheable("addresses")
public String getAddress(Customer customer) {...}
A chamadagetAddress() verificará primeiro o cacheaddresses antes de realmente chamar o método e, em seguida, armazenar em cache o resultado.
Embora na maioria dos casos, um cache seja suficiente, a estrutura Spring também suporta vários caches a serem passados como parâmetros:
@Cacheable({"addresses", "directory"})
public String getAddress(Customer customer) {...}
____ Nesse caso, se qualquer um dos caches contiver o resultado necessário, o resultado será retornado e o método não será invocado.
4.2. @CacheEvict __
Agora, qual seria o problema em fazer todos os métodos@Cacheable?
O problema é o tamanho -we don’t want to populate the cache with values that we don’t need often. Os caches podem crescer muito grandes, muito rapidamente e poderíamos estar mantendo muitos dados antigos ou não utilizados.
A anotação@CacheEvict é usada para indicar a remoção de um ou mais / todos os valores - para que novos valores possam ser carregados no cache novamente:
@CacheEvict(value="addresses", allEntries=true)
public String getAddress(Customer customer) {...}
Aqui, estamos usando o parâmetro adicionalallEntries em conjunto com o cache a ser esvaziado - para limpar todas as entradas no cacheaddressese prepará-lo para novos dados.
__ 4.3. @CachePut
Embora@CacheEvict reduza a sobrecarga de pesquisa de entradas em um cache grande removendo entradas obsoletas e não utilizadas, idealmente, você desejaavoid evicting too much data out of the cache.
Em vez disso, você deseja atualizar de forma seletiva e inteligente as entradas sempre que forem alteradas.
Com a anotação@CachePut, você pode atualizar o conteúdo do cache sem interferir na execução do método. Ou seja, o método sempre seria executado e o resultado armazenado em cache.
@CachePut(value="addresses")
public String getAddress(Customer customer) {...}
A diferença entre@Cacheable e@CachePut é que@Cacheable iráskip running the method, enquanto@CachePut iráactually run the methode colocará seus resultados no cache.
4.4. @Caching
E se você quiser usar várias anotações do mesmo tipo para armazenar em cache um método. Veja o exemplo incorreto abaixo:
@CacheEvict("addresses")
@CacheEvict(value="directory", key=customer.name)
public String getAddress(Customer customer) {...}
O código acima falharia ao compilar, pois o Java não permite que várias anotações do mesmo tipo sejam declaradas para um determinado método.
A solução alternativa para o problema acima seria:
@Caching(evict = {
@CacheEvict("addresses"),
@CacheEvict(value="directory", key="#customer.name") })
public String getAddress(Customer customer) {...}
Conforme mostrado no trecho de código acima, você podegroup multiple caching annotations com@Caching e usá-lo para implementar sua própria lógica de cache personalizada.
4.5. @CacheConfig
Com a anotação@CacheConfig, você podestreamline some of the cache configuration into a single place – at the class level - para que não precise declarar coisas várias vezes:
@CacheConfig(cacheNames={"addresses"})
public class CustomerDataService {
@Cacheable
public String getAddress(Customer customer) {...}
5. Cache Condicional
Às vezes, o armazenamento em cache pode não funcionar bem para um método em todas as situações.
Por exemplo - reutilizando nosso exemplo da anotação@CachePut - isso executará o método e também armazenará em cache os resultados todas as vezes:
@CachePut(value="addresses")
public String getAddress(Customer customer) {...}
5.1. Parâmetro de Condição
Agora - se quisermos mais controle sobre quando a anotação está ativa -@CachePut pode ser parametrizado com um parâmetro de condição que usa uma expressão SpEL para garantir que os resultados sejam armazenados em cache com base na avaliação dessa expressão:
@CachePut(value="addresses", condition="#customer.name=='Tom'")
public String getAddress(Customer customer) {...}
5.2. A menos que o parâmetro
Também podemos controlar o cachebased on the output of the method rather than the input - por meio do parâmetrounless:
@CachePut(value="addresses", unless="#result.length()<64")
public String getAddress(Customer customer) {...}
A anotação acima armazenaria em cache os endereços, a menos que tenham menos de 64 caracteres.
É importante saber que os parâmetrosconditioneunless podem ser usados em conjunto com todas as anotações de cache.
Esse tipo de armazenamento em cache condicional pode ser bastante útil para gerenciar grandes resultados e personalizar o comportamento com base nos parâmetros de entrada, em vez de impor um comportamento genérico a todas as operações.
6. Cache declarativo baseado em XML
Caso você não tenha acesso ao código-fonte do seu aplicativo ou queira injetar o comportamento do cache externamente, você também pode usar o cache declarativo baseado em XML.
Aqui está a nossa configuração XML:
Related
- Spring Security - Cabeçalhos de controle de cache
- Introdução ao JCache
- Cache de goiaba
- Ativos estáticos captáveis com Spring MVC
- Introdução à cafeína
- Introdução ao Ehcache
- Spring Cache - Criando um KeyGenerator personalizado
- Cache de segundo nível de hibernação
- Introdução ao Guava CacheLoader
- Despejo de cache na inicialização do Spring