21‐Lazy‐Initialization - JulianeMaran32/Java-with-Spring-Boot GitHub Wiki
49. Lazy Initialization - Visão Geral
🔄 Inicialização dos Beans
- Por padrão, quando sua aplicação Spring inicia, todos os beans são criados imediatamente.
- Isso inclui todos os beans anotados com
@Component
,@Service
,@Repository
,@Controller
, etc. - O Spring cria uma instância de cada bean e os deixa prontos para uso.
println
no construtor
🛠 Diagnóstico: adicionando @Component
public class CricketCoach implements Coach {
public CricketCoach() {
System.out.println("In constructor: " + getClass().getSimpleName());
}
}
getClass().getSimpleName()
imprime o nome da classe, útil para ver quais beans estão sendo instanciados.
▶ Quando iniciamos a aplicação:
In constructor: BaseballCoach
In constructor: CricketCoach
In constructor: TennisCoach
In constructor: TrackCoach
- Isso mostra que todos os beans são criados na inicialização, mesmo que não sejam usados ainda.
💤 O que é Lazy Initialization?
- Lazy Initialization significa que o bean só será criado quando for realmente necessário.
- Um bean só é inicializado se:
- For usado em uma injeção de dependência.
- For solicitado diretamente no código.
@Lazy
em uma classe
🔧 Usando import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
@Lazy
@Component
public class TrackCoach implements Coach {
public TrackCoach() {
System.out.println("In constructor: " + getClass().getSimpleName());
}
}
CricketCoach
✅ Injetando apenas o @RestController
public class DemoController {
private Coach myCoach;
@Autowired
public DemoController(@Qualifier(value = "cricketCoach") Coach myCoach) {
this.myCoach = myCoach;
}
}
- Nesse exemplo, o
TrackCoach
não será inicializado, pois não está sendo injetado.
Saída esperada:
In constructor: BaseballCoach
In constructor: CricketCoach
In constructor: TennisCoach
🧩 E os outros beans?
- Se quiser aplicar Lazy Initialization a outros beans, será necessário adicionar
@Lazy
em cada classe. - Isso pode se tornar trabalhoso em aplicações grandes.
application.properties
🌐 Configuração Global com Para ativar Lazy Initialization para todos os beans, use:
spring.main.lazy-initialization=true
- Agora, nenhum bean será criado até que seja realmente necessário.
- Até mesmo o
DemoController
só será criado quando sua rota for acessada.
println
no DemoController
🖨 Adicionando @Component
public class CricketCoach implements Coach {
public CricketCoach() {
System.out.println("In constructor: " + getClass().getSimpleName());
}
}
@RestController
public class DemoController {
private Coach myCoach;
@Autowired
public DemoController(@Qualifier(value = "cricketCoach") Coach myCoach) {
System.out.println("In constructor: " + getClass().getSimpleName());
this.myCoach = myCoach;
}
}
🔁 Como funciona o carregamento?
- O usuário acessa o endpoint REST
/dailywork
. - O Spring identifica que precisa do
DemoController
. - Para criar o
DemoController
, ele precisa doCricketCoach
. - Então o Spring cria primeiro o
CricketCoach
, depois oDemoController
.
Saída esperada:
In constructor: CricketCoach
In constructor: DemoController
⚖️ Vantagens e Desvantagens
✅ Vantagens
- Cria os objetos somente quando são usados.
- Pode melhorar o tempo de inicialização da aplicação, especialmente se ela tiver muitos beans.
⚠️ Desvantagens
- Beans como
@RestController
não serão criados até serem chamados pela primeira vez. - Problemas de configuração só serão detectados no momento da criação, e não na inicialização.
- É preciso garantir que o sistema tenha memória suficiente para os beans quando forem carregados.
🧠 Dica final
- Lazy Initialization está desativado por padrão.
- Antes de ativá-lo, teste e analise sua aplicação.
- Evite a otimização prematura — só use se realmente trouxer benefícios.
50. Lazy Initialization - Codificação - Parte 1
Etapas desta aula:
- Remover a anotação
@Primary
- Utilizar
@Qualifier
para definir qual implementação será injetada - Adicionar prints nos construtores para observar a criação dos objetos
Exemplo de código:
@RestController
public class DemoController {
private Coach myCoach;
@Autowired
public DemoController(@Qualifier("cricketCoach") Coach myCoach) {
System.out.println("In constructor: " + getClass().getSimpleName());
this.myCoach = myCoach;
}
@GetMapping("/dailyworkout")
public String getDailyWorkout() {
return myCoach.getDailyWorkout();
}
}
@Component
public class BaseballCoach implements Coach {
public BaseballCoach() {
System.out.println("In constructor: " + getClass().getSimpleName());
}
@Override
public String getDailyWorkout() {
return "Spend 30 minutes in batting practice";
}
}
@Component
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";
}
}
@Component
public class TennisCoach implements Coach {
public TennisCoach() {
System.out.println("In constructor: " + getClass().getSimpleName());
}
@Override
public String getDailyWorkout() {
return "Practice your backhand volley";
}
}
@Component
public class TrackCoach implements Coach {
public TrackCoach() {
System.out.println("In constructor: " + getClass().getSimpleName());
}
@Override
public String getDailyWorkout() {
return "Run a hard 5k!";
}
}
Resultado da execução:
Quando executamos o projeto e acessamos o endpoint http://localhost:8080/dailyworkout
, o Spring cria e carrega todas as classes marcadas com @Component
, mesmo que nem todas estejam sendo utilizadas.
O log mostra a seguinte saída:
In constructor: BaseballCoach
In constructor: CricketCoach
In constructor: TennisCoach
In constructor: TrackCoach
In constructor: DemoController
51. Lazy Initialization - Codificação - Parte 2
@Lazy
Tornando uma classe "preguiçosa" com Se queremos que um bean só seja criado quando for realmente necessário, podemos usar a anotação @Lazy
.
@Lazy
@Component
public class TrackCoach implements Coach {
public TrackCoach() {
System.out.println("In constructor: " + getClass().getSimpleName());
}
@Override
public String getDailyWorkout() {
return "Run a hard 5k!";
}
}
@Lazy
:
Resultado após aplicar Se a classe TrackCoach
não está sendo usada diretamente em nenhum lugar (não é injetada), o Spring não irá instanciá-la:
In constructor: BaseballCoach
In constructor: CricketCoach
In constructor: TennisCoach
In constructor: DemoController
Ou seja, o TrackCoach
não aparece no log — pois o Spring não precisou dele.
Inicialização preguiçosa global
Se quisermos que todos os beans sejam carregados somente quando forem utilizados, podemos configurar isso no arquivo application.properties
:
spring.main.lazy-initialization=true
Resultado:
Com essa configuração, o Spring só cria os beans no momento exato em que forem necessários:
In constructor: CricketCoach
In constructor: DemoController
Isso acontece porque o DemoController
precisa do CricketCoach
, então apenas esses dois foram instanciados. Os outros beans (BaseballCoach
, TennisCoach
, TrackCoach
) não foram carregados porque não foram utilizados.
Conclusão
- Por padrão, o Spring cria todos os beans na inicialização da aplicação.
- Com
@Lazy
, podemos indicar que um bean só deve ser criado quando for realmente necessário. - Também é possível ativar a inicialização preguiçosa globalmente, com a propriedade
spring.main.lazy-initialization=true
. - Isso pode melhorar o tempo de inicialização da aplicação e economizar recursos, especialmente em aplicações grandes.