Técnico

Spring 3.1 RC1 – Cache Abstraction

Spring Cache Abstraction

Abordamos um das novas funcionalidades do Spring 3.1 RC1, profiles e environments. Ainda existem outras funcionalidades, mas hoje iremos dar uma olhada em Cache Abstraction.

Cache Abstraction é literalmente uma abstração out of the box para adicionar uma camada de cache sobre seus beans, usando uma arquitetura AOP para gerenciar o que deve e o que não deve ser feito o cache.
Usar a nova camada de cache é muito fácil se você já está habituado com Spring, e veremos uma das diferentes maneiras de configurar seus beans.

Baixando a Denpendência

Para quem utiliza maven, basta adicionar a seguinte dependência no pom do seu projeto:

[cc lang=”xml” width=”100%”]

org.springframework.maven.milestone
Spring Maven Milestone Repository
http://maven.springframework.org/milestone

org.springframework
spring-core
3.1.0.RC1

org.springframework
spring-context
3.1.0.RC1

[/cc]

Se você perferir, pode baixar os jar direto do site do spring.
Sem segredos aqui, basta adicionar as dependências ao projeto e está pronto para usar.

Entendendo o funcionamento

A maneira com que o cache funciona é bem simples. Você pode enxergar o cache como um mapa chave-valor, onde a chave é o conjunto de argumentos do seu método, e o valor é o valor devolvido pelo seu método. Pensando assim fica fácil entender o funcionamento que irei mostrar no exemplo.
Referente a configuração do Spring, é necessário instanciar um gerenciador de cache, ou na linguagem spring, cacheManager. Existe algumas implementações de cache manager disponí­vel no spring, portanto iremos utilizar uma delas em nosso exemplo.
Vamos escrever um teste unitário com JUnit 4.8.1 para ilustrar o comportamento do cache.
Comece criando um arquivo padrão de beans do spring, mas com um namespace a mais:

[cc lang=”XML” width=”100%”]

[/cc]

Repare que estamos utilizando o namespace de cache além dos usuais.
A única configuração que iremos fazer aqui, é a do cache manager. Crie um bean da classe SimpleCacheManager e adicione o seguinte bean como cache gerenciado:

[cc lang=”XML” width=”100%”]

[/cc]

O que fizemos foi criar um cache manager simples do spring, e dentro configuramos o cache que iremos utilizar, associando a ele o nome de property. Repare também que estamos utilizando o cache implementado com um ConcurrentMap do java, garantindo o acesso thread safe ao cache.

Configuração por Anotação

Agora que configuramos o cache, vamos criar nossos beans que serão cacheados.
Vamos abordar primeiro a configuração por anotação em nossos beans. Para isso adicione a seguinte tag no seu xml de beans:

[cc lang=”XML” width=”100%”]

[/cc]

Assim será criado o proxy de cache em torno de todos os beans anotados.
Como não estou usando nenhuma biblioteca de proxy dinâmico, vamos criar uma interface para anotar nossas configurações:

[cc lang=”java” width=”100%”]
public interface CacheableTest {

@CacheEvict(value = “property”, allEntries = true)
void evictCache();

@Cacheable(“property”)
String getForCache(String s);

String getProperty();

void setProperty(String property);

}
[/cc]

Repare no getter e setter que usaremos no teste, e na anotação @Cacheable(“property”). Esta anotação está dizendo que o valor que este método devolver será armazenado no cache que configuramos previamente como property. Fato importante é que este valor é referente ao argumento passado como parâmetro no método.
A outra anotação @CacheEvict(value = “property”, allEntries = true) descreve o método que chamaremos para esvaziar o cache. Note que passamos o nome do cache, e que ele deve limpar todos os valores.
ɉ importante notar também que pode ser passado mais de um nome de cache em ambas as anotações.
Uma implementação básica para nosso bean pode ser:

[cc lang=”java” width=”100%”]
@Component(“cacheBean”)
public class CacheableBean implements CacheableTest {

private String property;

public String getForCache(String s) {
return this.property;
}

public String getProperty() {
return property;
}

public void setProperty(String property) {
this.property = property;
}

public void evictCache() {
// Não faz nada
}
}
[/cc]

Estou usando o package scan para instanciar o bean. Agora nosso teste:

[cc lang=”java” width=”100%”]
public class CacheTest {

@Test
public void testCache() {

ApplicationContext ctx = new ClassPathXmlApplicationContext(
“spring31-test-beans.xml”);

CacheableTest bean = ctx.getBean(“cacheBean”, CacheableTest.class);

bean.setProperty(“teste”);

Assert.assertEquals(“teste”, bean.getProperty());
Assert.assertEquals(“teste”, bean.getForCache(“a”));

bean.setProperty(“teste2”);
Assert.assertEquals(“teste2”, bean.getProperty());
Assert.assertEquals(“teste”, bean.getForCache(“a”));
Assert.assertEquals(“teste2”, bean.getForCache(“b”));

bean.setProperty(“teste3”);
Assert.assertEquals(“teste3”, bean.getProperty());
Assert.assertEquals(“teste”, bean.getForCache(“a”));
Assert.assertEquals(“teste2”, bean.getForCache(“b”));

bean.evictCache();
bean.setProperty(“teste4”);
Assert.assertEquals(“teste4”, bean.getProperty());
Assert.assertEquals(“teste4”, bean.getForCache(“a”));
Assert.assertEquals(“teste4”, bean.getForCache(“b”));

}

}
[/cc]

O arquivo de beans se chama spring31-test-beans.xml.
Repare que estamos invocando o método getForCache passando alguns valores diferentes, e o valor devolvido é sempre igual, mesmo que depois setamos um valor diferente ao bean. Para atualizar o valor e limpar o cache, basta invocar o método evictCache que haví­amos anotado com @CacheEvict.
Vale a pena brincar um pouco com o funcionamento do cache, e até mesmo criar outros caches e ver o comportamento do evict em diferentes métodos.

ښltimas Considerações

As mesmas configurações que fizemos com anotações, pode-se fazer direto no XML. Não entrarei no detalhe pois o funcionamento é exatamente o mesmo, mas se você preferir basta olhar a documentação que é bem straightforward.
Lembre-se que esta camada de cache não possui nenhuma relação com o banco de dados, e deve ser usada com muito cuidado em tais casos, pois alguns erros de concistência podem aparecer devido a um cache desatualizado.
Vale a pena brincar com o cache manager, pois o spring suporta o uso do EhCache, o que pode ser muito útil se você já possui alguma configuração pré-definida para sua aplicação.

Por enquanto é isso, qualquer dúvida mande nos comentários que responderei assim que possí­vel.

Por @Gust4v0_H4xx0r

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Compartilhe isso: