Quiz: Dependency Injection
Test your knowledge on advanced dependency injection.
30 questions - Click on each question to reveal the answer.
Questions 1-15: Types of Injection
Question 1: What are the three types of dependency injection?
Answer:
- Constructor injection (recommended)
- Setter injection
- Field injection
Question 2: Why is constructor injection recommended?
Answer:
- Immutable dependencies (final)
- Mandatory - no object without dependencies
- Testable - easy to mock
- Cycle detection at compile time
- No need for
@Autowired(Spring 4.3+)
Question 3: How to perform setter injection?
Answer:
@Service
public class UserService {
private UserRepository userRepository;
@Autowired
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
Used for optional or reconfigurable dependencies.
Question 4: Why avoid field injection?
Answer:
- Cannot make the dependency
final - Difficult to test without Spring
- Masks dependencies (not visible in the constructor)
- Facilitates SRP violations (too many dependencies)
// To avoid
@Autowired
private UserRepository repo;
Question 5: When is @Autowired optional?
Answer: Since Spring 4.3, if a class has a single constructor, @Autowired is implicit.
@Service
public class UserService {
private final UserRepository repo;
// @Autowired optional
public UserService(UserRepository repo) {
this.repo = repo;
}
}
Question 6: How to handle multiple constructors?
Answer: Explicitly mark the constructor to use:
@Service
public class UserService {
public UserService() { }
@Autowired // Spring will use this one
public UserService(UserRepository repo) {
this.repo = repo;
}
}
Question 7: How to make a dependency optional?
Answer: Several ways:
// 1. required = false
@Autowired(required = false)
private CacheService cache;
// 2. Optional (recommended)
public MyService(Optional<CacheService> cache) {
this.cache = cache.orElse(null);
}
// 3. @Nullable
public MyService(@Nullable CacheService cache) { }
Question 8: How to inject all implementations of an interface?
Answer:
@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));
}
}
Question 9: How to inject a Map of beans?
Answer:
@Service
public class ProcessorManager {
// Key = bean name, Value = instance
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);
}
}
Question 10: What is @Primary used for?
Answer: Designate the default bean when multiple implementations exist:
@Service
@Primary
public class EmailNotification implements NotificationService { }
@Service
public class SmsNotification implements NotificationService { }
// EmailNotification will be injected by default
Question 11: What is @Qualifier used for?
Answer: Specify which bean to inject:
@Service("email")
public class EmailNotification implements NotificationService { }
@Service("sms")
public class SmsNotification implements NotificationService { }
// Injection
public MyService(@Qualifier("sms") NotificationService notif) { }
Question 12: How to create a custom @Qualifier?
Answer:
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
public @interface Premium { }
@Service
@Premium
public class PremiumNotification implements NotificationService { }
// Usage
public MyService(@Premium NotificationService notif) { }
Question 13: What is @Lazy?
Answer: Delays bean creation until first access:
@Service
@Lazy
public class HeavyService { }
// Or at injection
public MyService(@Lazy HeavyService heavy) { }
Used for: startup performance, circular dependencies.
Question 14: How to resolve a circular dependency?
Answer:
- Refactor (best choice)
- Use
@Lazyon one of the dependencies - Use setter injection
@Service
public class A {
public A(@Lazy B b) { this.b = b; }
}
@Service
public class B {
public B(A a) { this.a = a; }
}
Question 15: How to inject configuration values?
Answer: With @Value:
@Service
public class EmailService {
@Value("${app.email.sender}")
private String sender;
@Value("${app.email.enabled:true}")
private boolean enabled;
// Or via constructor
public EmailService(@Value("${app.email.host}") String host) { }
}
Questions 16-30: Advanced Cases
Question 16: What is the difference between @Autowired and @Resource?
Answer:
@Autowired: Spring, injection by type@Resource: Java EE (JSR-250), injection by name
@Autowired // By type
private UserService userService;
@Resource(name = "specificService") // By name
private UserService userService;
Question 17: How to inject the Spring context itself?
Answer:
@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);
}
}
Question 18: How to programmatically obtain a bean?
Answer:
@Service
public class BeanFactory {
private final ApplicationContext context;
public BeanFactory(ApplicationContext context) {
this.context = context;
}
public UserService getUserService() {
return context.getBean(UserService.class);
}
}
Question 19: What is ObjectProvider?
Answer: A safe way to obtain optional or multiple beans:
@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(...));
}
}
Question 20: How to inject a prototype bean into a singleton?
Answer: Use ObjectProvider or @Lookup:
// Option 1: ObjectProvider
@Service
public class SingletonService {
private final ObjectProvider<PrototypeBean> provider;
public void doWork() {
PrototypeBean bean = provider.getObject(); // New instance
}
}
// Option 2: @Lookup
@Service
public abstract class SingletonService {
@Lookup
protected abstract PrototypeBean getPrototype();
}
Question 21: What is @DependsOn?
Answer: Forces the creation order of beans:
@Service
@DependsOn("databaseInitializer")
public class UserService {
// Created AFTER databaseInitializer
}
Question 22: How to exclude a bean from auto-configuration?
Answer:
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class MyApp { }
// Or in application.yml
spring:
autoconfigure:
exclude:
- org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
Question 23: How to create a conditional bean?
Answer:
@Bean
@ConditionalOnProperty(name = "cache.enabled", havingValue = "true")
public CacheManager cacheManager() { }
@Bean
@ConditionalOnMissingBean
public DefaultService defaultService() { }
@Bean
@Profile("dev")
public DevService devService() { }
Question 24: What is @Order?
Answer: Defines the priority order for collected beans:
@Component
@Order(1)
public class FirstFilter implements Filter { }
@Component
@Order(2)
public class SecondFilter implements Filter { }
// Injection in order
public MyService(List<Filter> filters) {
// FirstFilter, SecondFilter
}
Question 25: How to inject the Spring environment?
Answer:
@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");
}
}
Question 26: How to test a service with injection?
Answer:
@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();
}
}
Question 27: How to inject grouped properties?
Answer: With @ConfigurationProperties:
@ConfigurationProperties(prefix = "app.mail")
public class MailProperties {
private String host;
private int port;
private boolean ssl;
// getters/setters
}
// Injection
@Service
public class MailService {
public MailService(MailProperties props) { }
}
Question 28: What is the difference between @Component and @Bean?
Answer:
| @Component | @Bean |
|---|---|
| On class | On method |
| Auto-detected by scan | Explicitly declared |
| Limited configuration | Full control |
Use @Bean for external classes or complex configuration.
Question 29: How to have multiple instances of the same bean?
Answer:
@Configuration
public class DataSourceConfig {
@Bean
@Qualifier("primary")
public DataSource primaryDataSource() { }
@Bean
@Qualifier("secondary")
public DataSource secondaryDataSource() { }
}
// Injection
public MyService(
@Qualifier("primary") DataSource primary,
@Qualifier("secondary") DataSource secondary) { }
Question 30: What are common injection problems?
Answer:
- NoSuchBeanDefinitionException: missing bean
- NoUniqueBeanDefinitionException: multiple candidates
- BeanCurrentlyInCreationException: circular dependency
- UnsatisfiedDependencyException: injection failed
Solutions: check annotations, @Qualifier, @Primary, @Lazy.
Score
| Score | Level |
|---|---|
| 27-30 | Excellent - Mastered injection |
| 21-26 | Good - Some revisions needed |
| 15-20 | Average - Review the chapter |
| Less than 15 | Needs improvement |