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:
- Injeção via construtor (recomendada)
- Injeção via setter
- 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:
- Refatorar (melhor escolha)
- Usar
@Lazyem uma das dependências - 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 classe | No método |
| Detectado automaticamente por scan | Declarado explicitamente |
| Configuração limitada | Controle 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:
- NoSuchBeanDefinitionException: bean ausente
- NoUniqueBeanDefinitionException: múltiplos candidatos
- BeanCurrentlyInCreationException: dependência circular
- UnsatisfiedDependencyException: injeção falhou
Soluções: verifique anotações, @Qualifier, @Primary, @Lazy.
Pontuação
| Pontuação | Nível |
|---|---|
| 27-30 | Excelente - Injeção dominada |
| 21-26 | Bom - Algumas revisões |
| 15-20 | Médio - Releia o capítulo |
| Menos de 15 | Precisa revisar |