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!

Leave a Response

Recent Posts

Tag Cloud

advice annotations aop api aspect bean bytecode compilador configuração crosscuting eclipse framework ide jar java jdk jee jme join point jre jse máquina virtual netbeans pointcut produtividade spring weaving web

Meta

Java Framework Portal is proudly powered by WordPress and the SubtleFlux theme.

Copyright © Java Framework Portal