Pular para o conteúdo principal

Quiz: Injeção de Dependências

Teste seus conhecimentos sobre injeção de dependências avançada.

30 questões - Clique em cada pergunta para revelar a resposta.


Questões 1-15: Tipos de Injeção​

Pergunta 1: Quais são os três tipos de injeção de dependências?

Resposta:

  1. Injeção via construtor (recomendada)
  2. Injeção via setter
  3. Injeção via campo (field injection)

Pergunta 2: Por que a injeção via construtor é recomendada?

Resposta:

  • Dependências imutáveis (final)
  • Obrigatórias - não existe objeto sem dependências
  • Testável - fácil de mockar
  • Detecção de ciclos em tempo de compilação
  • Não precisa de @Autowired (Spring 4.3+)

Pergunta 3: Como fazer uma injeção via setter?

Resposta:

@Service
public class UserService {

private UserRepository userRepository;

@Autowired
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
}

Usado para dependências opcionais ou reconfiguráveis.


Pergunta 4: Por que evitar a injeção via campo?

Resposta:

  • Não é possível tornar a dependência final
  • Difícil de testar sem Spring
  • Esconde as dependências (não visível no construtor)
  • Facilita violações do SRP (muitas dependências)
// Evitar
@Autowired
private UserRepository repo;

Pergunta 5: Quando @Autowired é opcional?

Resposta: Desde o Spring 4.3, se uma classe tem apenas um construtor, @Autowired é implícito.

@Service
public class UserService {
private final UserRepository repo;

// @Autowired opcional
public UserService(UserRepository repo) {
this.repo = repo;
}
}

Pergunta 6: Como lidar com múltiplos construtores?

Resposta: Marque explicitamente o construtor a ser usado:

@Service
public class UserService {

public UserService() { }

@Autowired // Spring usará este
public UserService(UserRepository repo) {
this.repo = repo;
}
}

Pergunta 7: Como tornar uma dependência opcional?

Resposta: Várias formas:

// 1. required = false
@Autowired(required = false)
private CacheService cache;

// 2. Optional (recomendado)
public MyService(Optional<CacheService> cache) {
this.cache = cache.orElse(null);
}

// 3. @Nullable
public MyService(@Nullable CacheService cache) { }

Pergunta 8: Como injetar todas as implementações de uma interface?

Resposta:

@Service
public class NotificationManager {

private final List<NotificationService> services;

public NotificationManager(List<NotificationService> services) {
this.services = services;
}

public void notifyAll(String msg) {
services.forEach(s -> s.send(msg));
}
}

Pergunta 9: Como injetar um Map de beans?

Resposta:

@Service
public class ProcessorManager {

// Chave = nome do bean, Valor = instância
private final Map<String, Processor> processors;

public ProcessorManager(Map<String, Processor> processors) {
this.processors = processors;
}

public void process(String type, Data data) {
processors.get(type).process(data);
}
}

Pergunta 10: Para que serve @Primary?

Resposta: Designar o bean padrão quando existem várias implementações:

@Service
@Primary
public class EmailNotification implements NotificationService { }

@Service
public class SmsNotification implements NotificationService { }

// EmailNotification será injetado por padrão

Pergunta 11: Para que serve @Qualifier?

Resposta: Especificar qual bean injetar:

@Service("email")
public class EmailNotification implements NotificationService { }

@Service("sms")
public class SmsNotification implements NotificationService { }

// Injeção
public MyService(@Qualifier("sms") NotificationService notif) { }

Pergunta 12: Como criar um @Qualifier personalizado?

Resposta:

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
public @interface Premium { }

@Service
@Premium
public class PremiumNotification implements NotificationService { }

// Uso
public MyService(@Premium NotificationService notif) { }

Pergunta 13: O que é @Lazy?

Resposta: Adia a criação do bean até o primeiro acesso:

@Service
@Lazy
public class HeavyService { }

// Ou na injeção
public MyService(@Lazy HeavyService heavy) { }

Usado para: performance na inicialização, dependências circulares.


Pergunta 14: Como resolver uma dependência circular?

Resposta:

  1. Refatorar (melhor escolha)
  2. Usar @Lazy em uma das dependências
  3. Usar injeção via setter
@Service
public class A {
public A(@Lazy B b) { this.b = b; }
}

@Service
public class B {
public B(A a) { this.a = a; }
}

Pergunta 15: Como injetar valores de configuração?

Resposta: Com @Value:

@Service
public class EmailService {

@Value("${app.email.sender}")
private String sender;

@Value("${app.email.enabled:true}")
private boolean enabled;

// Ou via construtor
public EmailService(@Value("${app.email.host}") String host) { }
}

Questões 16-30: Casos Avançados​

Pergunta 16: Qual a diferença entre @Autowired e @Resource?

Resposta:

  • @Autowired: Spring, injeção por tipo
  • @Resource: Java EE (JSR-250), injeção por nome
@Autowired  // Por tipo
private UserService userService;

@Resource(name = "specificService") // Por nome
private UserService userService;

Pergunta 17: Como injetar o próprio contexto do Spring?

Resposta:

@Service
public class DynamicBeanLoader implements ApplicationContextAware {

private ApplicationContext context;

@Override
public void setApplicationContext(ApplicationContext ctx) {
this.context = ctx;
}

public Object getBean(String name) {
return context.getBean(name);
}
}

Pergunta 18: Como obter um bean de forma programática?

Resposta:

@Service
public class BeanFactory {

private final ApplicationContext context;

public BeanFactory(ApplicationContext context) {
this.context = context;
}

public UserService getUserService() {
return context.getBean(UserService.class);
}
}

Pergunta 19: O que é ObjectProvider?

Resposta: Uma forma segura de obter beans opcionais ou múltiplos:

@Service
public class MyService {

private final ObjectProvider<CacheService> cacheProvider;

public MyService(ObjectProvider<CacheService> cacheProvider) {
this.cacheProvider = cacheProvider;
}

public void doWork() {
cacheProvider.ifAvailable(cache -> cache.put(...));
}
}

Pergunta 20: Como injetar um bean prototype em um singleton?

Resposta: Usar ObjectProvider ou @Lookup:

// Opção 1: ObjectProvider
@Service
public class SingletonService {
private final ObjectProvider<PrototypeBean> provider;

public void doWork() {
PrototypeBean bean = provider.getObject(); // Nova instância
}
}

// Opção 2: @Lookup
@Service
public abstract class SingletonService {
@Lookup
protected abstract PrototypeBean getPrototype();
}

Pergunta 21: O que é @DependsOn?

Resposta: Força a ordem de criação dos beans:

@Service
@DependsOn("databaseInitializer")
public class UserService {
// Criado APÓS databaseInitializer
}

Pergunta 22: Como excluir um bean da auto-configuração?

Resposta:

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class MyApp { }

// Ou em application.yml
spring:
autoconfigure:
exclude:
- org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

Pergunta 23: Como criar um bean condicional?

Resposta:

@Bean
@ConditionalOnProperty(name = "cache.enabled", havingValue = "true")
public CacheManager cacheManager() { }

@Bean
@ConditionalOnMissingBean
public DefaultService defaultService() { }

@Bean
@Profile("dev")
public DevService devService() { }

Pergunta 24: O que é @Order?

Resposta: Define a ordem de prioridade para beans coletados:

@Component
@Order(1)
public class FirstFilter implements Filter { }

@Component
@Order(2)
public class SecondFilter implements Filter { }

// Injeção na ordem
public MyService(List<Filter> filters) {
// FirstFilter, SecondFilter
}

Pergunta 25: Como injetar o ambiente do Spring?

Resposta:

@Service
public class ConfigService {

private final Environment env;

public ConfigService(Environment env) {
this.env = env;
}

public String getProperty(String key) {
return env.getProperty(key);
}

public boolean isDev() {
return Arrays.asList(env.getActiveProfiles()).contains("dev");
}
}

Pergunta 26: Como testar um serviço com injeção?

Resposta:

@ExtendWith(MockitoExtension.class)
class UserServiceTest {

@Mock
private UserRepository userRepository;

@InjectMocks
private UserService userService;

@Test
void shouldFindUser() {
when(userRepository.findById(1L)).thenReturn(Optional.of(user));

User result = userService.findById(1L);

assertThat(result).isNotNull();
}
}

Pergunta 27: Como injetar propriedades agrupadas?

Resposta: Com @ConfigurationProperties:

@ConfigurationProperties(prefix = "app.mail")
public class MailProperties {
private String host;
private int port;
private boolean ssl;
// getters/setters
}

// Injeção
@Service
public class MailService {
public MailService(MailProperties props) { }
}

Pergunta 28: Qual a diferença entre @Component e @Bean?

Resposta:

@Component@Bean
Na classeNo método
Detectado automaticamente por scanDeclarado explicitamente
Configuração limitadaControle total

Use @Bean para classes externas ou configuração complexa.


Pergunta 29: Como ter múltiplas instâncias do mesmo bean?

Resposta:

@Configuration
public class DataSourceConfig {

@Bean
@Qualifier("primary")
public DataSource primaryDataSource() { }

@Bean
@Qualifier("secondary")
public DataSource secondaryDataSource() { }
}

// Injeção
public MyService(
@Qualifier("primary") DataSource primary,
@Qualifier("secondary") DataSource secondary) { }

Pergunta 30: Quais são os problemas comuns de injeção?

Resposta:

  1. NoSuchBeanDefinitionException: bean ausente
  2. NoUniqueBeanDefinitionException: múltiplos candidatos
  3. BeanCurrentlyInCreationException: dependência circular
  4. UnsatisfiedDependencyException: injeção falhou

Soluções: verifique anotações, @Qualifier, @Primary, @Lazy.


Pontuação​

PontuaçãoNível
27-30Excelente - Injeção dominada
21-26Bom - Algumas revisões
15-20Médio - Releia o capítulo
Menos de 15Precisa revisar

Voltar ao Módulo 5