Spring 3, configurando beans com Annotations
Posted on 15 March 2010
Hoje, é muito comum frameworks configuráveis através de annotations. O Spring também possui esse estilo de configuração que é bastante prático e traz produtividade ao desenvolvimento. Você poderá inclusive misturar configuração via XML e Annotations e utilizar qual for mais adequada para cada situação. Nesse tutorial mostraremos como a configuração pode ser feita através de annotations e ainda como pode ser feita a detecção automática dos beans através do classpath scanning.
Esse tutorial é continuação do Hello World com Spring 3 para um projeto WEB, se ainda não tem um projeto Spring configurado, é recomendável ler o outro tutorial antes de prosseguir com esse. Algumas anotações utilizadas nesse capítulo necessitam JEE 5 (como @PostConstruct).
1. Configurando os beans com annotations
Vamos começar configurando beans com Annotations, ao invés de usar a configuração de XML. Como é possível utilizar as duas configurações simultaneamente, a configuração feita através de Annotations é processada antes da configuração via XML. A configuração em XML pode então sobrescrever a configuração feita com Annotations.
Para habilitar a configuração dos beans via annotations, basta adicionar uma tag context:annotation-config no seu arquivo applicationContext.xml (Note a inclusão do namespace context)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config/>
</beans>
Com essa tag, será possível fazer a configuração dos beans por Annotations.
Vejamos as anotações (alguns dos exemplos mostrados foram retirados da documentação do Spring):
@Required
A anotação @Required é utilizada nos setters das propriedades do bean, veja o exemplo:
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Required
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// …
}
Essa anotação indica que essa propriedade deve ser populada na configuração. Caso não haja configuração para essa propriedade uma exceção será lançada pelo container.
@Autowired e @Inject
Como esperado, você pode utilizar a anotação @Autowired em métodos setter. Se estiver utilizando um JAR para o JSR-330 (Injeção de dependencia) poderá utilizar a anotação @Inject. O Spring detecta se o JAR está presente automaticamente. A anotação @Autowired faz a configuração da propriedade de forma automática, buscando na fábrica do Spring algum bean que possa satisfazer a dependencia e então realizando a configuração.
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Autowired
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// …
}
Propriedade anotadas com @Autowired devem ser obrigatoriamente preenchidas. Você pode alterar esse comportamento através do atributo required, como @Autowired(required=false). A anotação @Inject não tem a mesma definição, sendo o preenchimento opicional.
Também é possível utilizar essa anotação em métodos com nomes aleatórios e com vários argumentos:
public class MovieRecommender {
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
@Autowired
public void prepare(MovieCatalog movieCatalog, CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
}
// …
}
Você pode usar o @Autowired em construtores e campos:
public class MovieRecommender {
@Autowired
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
@Autowired
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
}
// …
}
@Value
A anotação @Value é utilizada quando temos propriedades que não são outros beans exemplo:
public class MovieCatalog {
@Value(“Comedy”)
String name;
}
@PostConstruct e @PreDestroy
As anotações @PostContruct e @PreDestroy servem para anotar métodos que devem ser chamados quando o container for iniciado e destruido respectivamente. É necessário ter um JAR do JSR-250 para ter disponíveis essas anotações. Se não tiver esse JAR disponível uma alternativa é utilizar os atributos init-method e destroy-method na definição do bean no XML do Spring. Ou o bean implementar as interfaces InitializingBean e DisposeableBean.
2. Contruindo uma aplicação utilizando Annotations
Utilizando uma aplicação que já esteja configurada com o Spring, vamos criar dois beans e utilizar a injeção de dependência através de annotations. Crie duas classes conforme o exemplo:
package org.javaframework.spring;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
public class MostraInformacoesSistema {
@Autowired
Sistema sistema;
@PostConstruct
public void mostraInformacoes(){
System.out.println("Sistema: "+sistema.getNome()+
", versão: "+sistema.getVersao());
}
}
package org.javaframework.spring;
import org.springframework.beans.factory.annotation.Value;
public class Sistema {
@Value("Spring com annotations")
String nome;
@Value("1.0")
String versao;
public String getNome() {
return nome;
}
public String getVersao() {
return versao;
}
public void setNome(String nome) {
this.nome = nome;
}
public void setVersao(String telefone) {
this.versao = telefone;
}
}
A classe Sistema servirá para guardarmos algumas informações que serão mostradas pela classe MostraInformacoesSistema. Foi utilizada a anotação @Autowired no atributo sistema da classe MostraInformacoesSistema, isso indica para o Spring fazer a configuração dessa propriedade automaticamente. A anotação @PostConstruct fará com que o método mostraInformacoes seja chamado assim que o bean esteja completamente configurado.
Agora vamos configurar o XML do Spring para ler essas anotações e fazer a configuração, configure seu arquivo applicationContext.cml conforme o exemplo:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config/>
<bean class="org.javaframework.spring.MostraInformacoesSistema"/>
<bean class="org.javaframework.spring.Sistema”/>
</beans>
Declaramos um bean da classe MostraInformacoesSistema e outro da classe Sistema. O Spring irá fazer a injeção do objeto Sistema no objeto MostraInformacoesSistema, graças a anotação @Autowired que utilizamos.
Ao testar a aplicação será impresso no console: Sistema: Spring com annotations, versão: 1.0
Outras informações sobre a configuração por anotações, assim como outras anotações disponíveis, podem ser vistas na documentação do Spring, seção 3.9 Annotation-based container configuration.
Fizemos a configuração do bean por annotations, mas ainda precisamos declarar o bean no XML. Isso porque a tag context:annotation-config apenas lê as anotações e faz a configuração, mas não implica em detectar as classes automaticamente. Para isso precisamos de outra tag, que será mostrada a seguir.
3. Classpath scanning
Classpath scanning é um recurso do Spring que lê o classpath da aplicação e busca classes que possam ser configuradas, isso evita que você tenha que declarar essas classes no XML. Essas classes são passadas por um filtro e então uma definição de um bean é criada para elas. Geralemente esse filtro é alguma anotação que marca que determinada classe deve ser utilizada como um componente. Essas anotações são: @Component, @Service, @Controller e @Repository (que foi introduzida no Spring 2.0). Você pode também criar suas próprias anotações e filtros para declarar os componentes.
A anotação @Component é um tipo genérico para qualquer bean que deve ser gerenciado pelo Spring. @Repository, @Service e @Controller são especializações de @Component e servem para as camadas de persistencia, serviço e apresentação respectivamente. Você pode utilizar @Component para qualquer classe da sua aplicação, mas utilizar uma anotação mais específica ajuda caso deseje criar um filtro, utilizar ferramentas, ou orientação a aspectos. Funcionalmente todas as anotações servem para declarar beans, não existe diferença entre elas a não ser na questão de organização da apliacação e utilidades citadas anteriormente.
Para detectar as classes e gerar beans precisamos de uma outra tag no applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="org.javaframework"/>
</beans>
Essa tag irá indicar ao Spring para procurar as classes e fazer a configuração dos beans. O atributo base-package indica em qual pacote as classes devem ser lidas, podem ser especificados quantos pacotes desejar, separados por vírgula.
Com essa tag, podemos alterar o applicationContext.xml da aplicação exemplo que criamos, retirando as declarações dos beans. O arquivo applicationContext.xml fica da seguinte forma:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config/>
<context:component-scan base-package="org.javaframework"/>
</beans>
As classes devem ter alguma anotação que indique que são componentes, utilizamos a anotação @Service
package org.javaframework.spring;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MostraInformacoesSistema {
@Autowired
Sistema sistema;
@PostConstruct
public void mostraInformacoes(){
System.out.println("Sistema: "+sistema.getNome()
+", versão: "+sistema.getVersao());
}
}
package org.javaframework.spring;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@Service
public class Sistema {
@Value("Spring com annotations")
String nome;
@Value("1.0")
String versao;
public String getNome() {
return nome;
}
public String getVersao() {
return versao;
}
public void setNome(String nome) {
this.nome = nome;
}
public void setVersao(String telefone) {
this.versao = telefone;
}
}
Agora, basta criar as classes e utilizar as anotações para fazer a configuração, contando que as classes estejam no pacote definido em base-package elas serão detectadas e configuradas automaticamente, sem a necessidade de intervenção no XML de configuração do Spring.
Mais informações sobre o classpath scanning podem ser obtidas na documentação do Spring, seção 3.10 Classpath Scanning and Managed Components.
No responses yet. You could be the first!