Skip to main content

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:

  1. Constructor injection (recommended)
  2. Setter injection
  3. 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:

  1. Refactor (best choice)
  2. Use @Lazy on one of the dependencies
  3. 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 classOn method
Auto-detected by scanExplicitly declared
Limited configurationFull 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:

  1. NoSuchBeanDefinitionException: missing bean
  2. NoUniqueBeanDefinitionException: multiple candidates
  3. BeanCurrentlyInCreationException: circular dependency
  4. UnsatisfiedDependencyException: injection failed

Solutions: check annotations, @Qualifier, @Primary, @Lazy.


Score​

ScoreLevel
27-30Excellent - Mastered injection
21-26Good - Some revisions needed
15-20Average - Review the chapter
Less than 15Needs improvement

Back to Module 5