22‐Bean Scopes - JulianeMaran32/Java-with-Spring-Boot GitHub Wiki
52. Bean Scopes - Visão Geral
- Escopo define o ciclo de vida de um bean:
- Por quanto tempo o bean permanece na memória?
- Quantas instâncias são criadas?
- Como essas instâncias são compartilhadas na aplicação?
Escopo Padrão
- O escopo padrão no Spring é o singleton.
- Por padrão, o Spring cria uma única instância (singleton) de cada bean.
- Essa instância é armazenada em memória e reutilizada sempre que o bean for necessário.
- Todas as injeções de dependência usarão essa mesma instância.
O que é Singleton?
- O container do Spring cria apenas uma instância do bean por padrão.
- Essa única instância é armazenada em cache e todas as injeções de dependência referenciam o mesmo objeto.
Exemplo:
@RestController
public class DemoController {
private Coach myCoach;
private Coach anotherCoach;
@Autowired
public DemoController(@Qualifier("cricketCoach") Coach theCoach,
@Qualifier("cricketCoach") Coach theAnotherCoach) {
this.myCoach = theCoach;
this.anotherCoach = theAnotherCoach;
}
// ...
}
- Nesse exemplo, como ambos os campos injetados usam o mesmo qualificador ("
cricketCoach
"), eles apontam para a mesma instância.
Especificando o Escopo do Bean de Forma Explícita
Você pode declarar explicitamente o escopo usando a anotação @Scope
:
@Component
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
public class CricketCoach implements Coach {
// ...
}
Outros Escopos Disponíveis no Spring
Escopo | Descrição |
---|---|
singleton | Apenas uma instância do bean é criada e compartilhada. (Padrão) |
prototype | Uma nova instância é criada cada vez que o bean é solicitado. |
request | Uma instância por requisição HTTP (aplicável apenas em web apps). |
session | Uma instância por sessão HTTP (apenas para web apps). |
application | Uma instância para o contexto de uma aplicação web (ServletContext). |
websocket | Uma instância por conexão de websocket (aplicável para web apps com websockets). |
Exemplo: Escopo Prototype
No escopo prototype, uma nova instância é criada para cada injeção.
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class CricketCoach implements Coach {
// ...
}
Com o seguinte controlador:
@RestController
public class DemoController {
private Coach myCoach;
private Coach anotherCoach;
@Autowired
public DemoController(@Qualifier("cricketCoach") Coach theCoach,
@Qualifier("cricketCoach") Coach theAnotherCoach) {
this.myCoach = theCoach;
this.anotherCoach = theAnotherCoach;
}
@GetMapping("/check")
public String check() {
return "Comparing beans: myCoach == anotherCoach, " + (myCoach == anotherCoach);
}
}
- Se o bean estiver em escopo singleton, a comparação (
myCoach == anotherCoach
) retornarátrue
. - Se estiver no escopo prototype, a comparação retornará
false
.
53. Bean Scopes - Codificação
Passos Realizados:
-
Housekeeping:
- Parar todas as aplicações.
- Fechar todas as janelas.
- Fazer uma cópia da pasta do projeto, renomeando, por exemplo, de
06-lazy-initialization
para07-beans-scopes
.
-
Limpeza de Configurações:
- Remover a anotação
@Lazy
. - Remover a configuração global
spring.main.lazy-initialization=true
do arquivoapplication.properties
.
- Remover a anotação
Código do DemoController (para testar o escopo):
@RestController
public class DemoController {
private Coach myCoach;
private Coach anotherCoach;
@Autowired
public DemoController(@Qualifier("cricketCoach") Coach theCoach,
@Qualifier("cricketCoach") Coach theAnotherCoach) {
this.myCoach = theCoach;
this.anotherCoach = theAnotherCoach;
}
@GetMapping("/dailyworkout")
public String getDailyWorkout() {
return myCoach.getDailyWorkout();
}
@GetMapping("/check")
public String check() {
return "Comparing beans: myCoach == anotherCoach, " + (myCoach == anotherCoach);
}
}
-
Resultado Esperado com Escopo Singleton:
Ao acessar o endpoint/check
, o retorno será:Comparing beans: myCoach == anotherCoach, true
-
Isso ocorre porque, no escopo singleton, todas as injeções referenciam a mesma instância.
Alterando para Escopo Prototype
Basta modificar a classe do bean para o escopo prototype:
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) // Nova instância para cada injeção
public class CricketCoach implements Coach {
public CricketCoach() {
System.out.println("In constructor: " + getClass().getSimpleName());
}
@Override
public String getDailyWorkout() {
return "Practice fast bowling for 15 minutes";
}
}
-
Resultado Esperado com Escopo Prototype:
Ao acessar o endpoint/check
, o retorno será:Comparing beans: myCoach == anotherCoach, false
-
Ou seja, cada injeção cria uma nova instância, e as referências são diferentes.
Conclusão
- O escopo singleton (padrão) cria uma única instância compartilhada em toda a aplicação.
- O escopo prototype cria uma nova instância para cada injeção ou solicitação.
- Você pode verificar o comportamento do escopo comparando as instâncias injetadas através de uma rota (por exemplo,
/check
).