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 atributonameou 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.