Gerenciamento de Beans com Anotações no Spring

1. Criando o Módulo spring-ioc-annotation

1.1 Estrutura do Módulo

Crie um módulo similar ao spring-ioc-xml e adicione o arquivo de log log4j2.xml. #### 1.2 Dependências (Maven)

<dependencies>
   <!-- Spring Context -->
   <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-context</artifactId>
       <version>6.0.3</version>
   </dependency>

   <!-- Testes JUnit5 -->
   <dependency>
       <groupId>org.junit.jupiter</groupId>
       <artifactId>junit-jupiter-api</artifactId>
       <version>5.9.2</version>
       <scope>test</scope>
   </dependency>

   <!-- Log4j2 -->
   <dependency>
       <groupId>org.apache.logging.log4j</groupId>
       <artifactId>log4j-core</artifactId>
       <version>2.19.0</version>
   </dependency>
   <dependency>
       <groupId>org.apache.logging.log4j</groupId>
       <artifactId>log4j-slf4j2-impl</artifactId>
       <version>2.19.0</version>
   </dependency>
</dependencies>

2. Ativando a Varredura de Componentes

Por padrão, o Spring não usa anotações para gerenciar beans. É necessário declarar no XML a tag <context:component-scan> para ativar a varredura automática. O pacote base (atributo base-package) e seus subpacotes serão escaneados; classes anotadas com @Component (ou suas especializações) serão registradas como beans. ```

<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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

<context:component-scan base-package="com.exemplo.spring"/>

Casos de Uso da Varredura

  • Varredura padrão: <context:component-scan base-package="com.exemplo.spring"/>
  • Excluir componentes específicos: ``` <context:component-scan base-package="com.exemplo.spring"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan>
  • Incluir apenas componentes específicos (desabilitar padrão): ``` <context:component-scan base-package="com.exemplo.spring" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan>
    
    

3. Definindo Beans com Anotações

O Spring fornece anotações para marcar classes como beans: | Anotação | Descrição | |---|---| | @Component | Anotação genérica para qualquer bean do Spring. | | @Repository | Indica um bean da camada de persistência (DAO). | | @Service | Indica um bean da camada de serviço (lógica de negócio). | | @Controller | Inddica um bean da camada de controle (MVC). |

3.1 Injeção com @Autowired

Por padrão, @Autowired realiza a injeção por tipo (byType). Pode ser aplicada em campos, construtores, métodos setter e parâmetros.

@Repository
public class UsuarioDaoImpl implements UsuarioDao {
   @Override
   public void imprimir() {
       System.out.println("DAO executado.");
   }
}

@Service
public class UsuarioServiceImpl implements UsuarioService {
   @Autowired
   private UsuarioDao usuarioDao;

   @Override
   public void executar() {
       usuarioDao.imprimir();
       System.out.println("Serviço executado.");
   }
}

@Controller
public class UsuarioController {
   @Autowired
   private UsuarioService usuarioService;

   public void acao() {
       usuarioService.executar();
       System.out.println("Controller executado.");
   }
}
Exemplo com Setter
@Service
public class UsuarioServiceImpl implements UsuarioService {
   private UsuarioDao usuarioDao;

   @Autowired
   public void setUsuarioDao(UsuarioDao usuarioDao) {
       this.usuarioDao = usuarioDao;
   }
   // ...
}
Exemplo com Construtor
@Service
public class UsuarioServiceImpl implements UsuarioService {
   private UsuarioDao usuarioDao;

   @Autowired
   public UsuarioServiceImpl(UsuarioDao usuarioDao) {
       this.usuarioDao = usuarioDao;
   }
   // ...
}

Nota: Se houver apenas um construtor com parâmetros, a anotação @Autowired pode ser omitida – o Spring a infere automaticamente.

Usando @Qualifier para resovler ambiguidade

Quando existem múltiplos beans do mesmo tipo, use @Qualifier para especificar o nome do bean desejado.

@Service
public class UsuarioServiceImpl implements UsuarioService {
   @Autowired
   @Qualifier("usuarioDaoImpl") // nome do bean (padrão: nome da classe com letra minúscula)
   private UsuarioDao usuarioDao;
   // ...
}

3.2 Injeção com @Resource

@Resource (do pacote jakarta.annotation) é uma alternativa padrão (JSR-250). Diferenças principais:

  • Por padrão, faz injeção por nome (byName). Se não encontrar pelo nome, tenta por tipo.
  • Não precisa do @Qualifier; o nome é definido pelo atributo name ou pelo nome do campo.
  • Pode ser aplicado apenas em campos e métodos setter.

Dependência necessária para JDK > 8 ou < 11:

<dependency>
   <groupId>jakarta.annotation</groupId>
   <artifactId>jakarta.annotation-api</artifactId>
   <version>2.1.1</version>
</dependency>
Exemplo com nome explícito
@Repository("meuDao")
public class UsuarioDaoImpl implements UsuarioDao {
   @Override
   public void imprimir() {
       System.out.println("DAO executado.");
   }
}

@Service
public class UsuarioServiceImpl implements UsuarioService {
   @Resource(name = "meuDao")
   private UsuarioDao meuDao;

   @Override
   public void executar() {
       meuDao.imprimir();
       System.out.println("Serviço executado.");
   }
}
Exemplo sem nome (usa o nome do campo)
@Service
public class UsuarioServiceImpl implements UsuarioService {
   @Resource
   private UsuarioDao meuDao; // procura por bean de nome "meuDao"
   // ...
}

Se o nome não corresponder a nenhum bean e houver apenas um bean do tipo, a injeção ocorrerá por tipo. Caso haja múltiplos beans do mesmo tipo, ocorrerá erro.

4. Desenvolvimento Totalmente com Anotações (Sem XML)

É possível eliminar o arquivo XML substituindo-o por uma classe de configuração anotada com @Configuration e @ComponentScan.

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.exemplo.spring")
public class ConfiguracaoSpring {
}

O contexto então é criado com AnnotationConfigApplicationContext:

@Test
public void testeCompleto() {
   ApplicationContext contexto = new AnnotationConfigApplicationContext(ConfiguracaoSpring.class);
   UsuarioController controller = contexto.getBean("usuarioController", UsuarioController.class);
   controller.acao();
   // logger.info("Sucesso");
}

Dessa forma, toda a configuração fica baseada em anotações, sem necessidade de XML.

Tags: Spring Anotações component-scan Autowired Resource

Publicado em 10-14 04:37