Spring Core Interview Questions
What is Inversion of Control (IoC)?
IoC means your classes do not create or look up their own dependencies; a container does it for them. In Spring the ApplicationContext creates objects (beans), wires them together and manages their lifecycle. Control over object creation is "inverted" from your code to the framework.
What is Dependency Injection and what types does Spring support?
DI is the way IoC is implemented: dependencies are passed in instead of created with new.
| Type | How | When to use |
|---|---|---|
| Constructor | dependencies are constructor parameters | Recommended: required dependencies, final fields, easy to test |
| Setter | @Autowired on a setter | optional dependencies |
| Field | @Autowired on a field | avoid: hidden dependencies, needs reflection in tests |
Why is constructor injection preferred over field injection?
- Fields can be
final, so the object is immutable and never half-built. - Dependencies are visible in the constructor; too many parameters signals a class doing too much.
- Unit tests can call
new OrderService(mockRepo)without Spring or reflection. - Circular dependencies fail fast at startup instead of hiding.
@Service
public class OrderService {
private final OrderRepository orderRepository;
private final PaymentClient paymentClient;
// single constructor: @Autowired is optional
public OrderService(OrderRepository orderRepository, PaymentClient paymentClient) {
this.orderRepository = orderRepository;
this.paymentClient = paymentClient;
}
}What is the difference between BeanFactory and ApplicationContext?
| BeanFactory | ApplicationContext |
|---|---|
| basic container: creates and wires beans | extends BeanFactory with enterprise features |
lazy: beans created on first getBean() | eager: singletons created at startup (errors found early) |
| no events, i18n or AOP auto-proxying | events, MessageSource, environment/profiles, AOP, annotation processing |
Spring Boot always uses an ApplicationContext (e.g. AnnotationConfigServletWebServerApplicationContext).
What is the difference between @Component, @Service, @Repository and @Controller?
All four are stereotypes that mark a class for component scanning; @Service, @Repository and @Controller are meta-annotated with @Component.
| Annotation | Layer | Extra behaviour |
|---|---|---|
@Component | generic | none |
@Service | business logic | none (documents intent) |
@Repository | data access | translates persistence exceptions to DataAccessException |
@Controller / @RestController | web | request mapping; @RestController adds @ResponseBody |
What is the difference between @Bean and @Component?
@Component goes on your own class and is picked up by component scanning. @Bean goes on a method inside a @Configuration class and is used for classes you cannot annotate (third-party: RestClient, ObjectMapper, PasswordEncoder) or when creation needs logic.
@Configuration
public class AppConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}What are the bean scopes in Spring?
| Scope | Instances |
|---|---|
singleton (default) | one per ApplicationContext |
prototype | a new one every time it is requested |
request | one per HTTP request (web) |
session | one per HTTP session (web) |
application | one per ServletContext |
Note: Singleton beans are shared by all threads, so they must be stateless (no per-request data in fields).
What happens when you inject a prototype bean into a singleton?
The prototype is injected once, when the singleton is created, so the singleton keeps using the same instance. To get a fresh one each time, inject ObjectProvider<T> and call getObject(), use a @Lookup method, or a scoped proxy (proxyMode = ScopedProxyMode.TARGET_CLASS).
Explain the Spring bean lifecycle.
instantiate (constructor) -> inject dependencies -> Aware callbacks (BeanNameAware, ApplicationContextAware) -> BeanPostProcessor.postProcessBeforeInitialization -> @PostConstruct -> InitializingBean.afterPropertiesSet -> init-method -> BeanPostProcessor.postProcessAfterInitialization (AOP proxies are created here) -> bean is ready ... context closes ... -> @PreDestroy -> DisposableBean.destroy -> destroy-method
@PostConstruct/@PreDestroy come from jakarta.annotation in Spring Boot 3.
How do you resolve "expected single matching bean but found 2"?
Two beans implement the same type (e.g. RazorpayGateway and StripeGateway implement PaymentGateway). Fix it with @Primary on the default one, or @Qualifier("razorpayGateway") at the injection point. You can also inject List<PaymentGateway> or Map<String, PaymentGateway> to get all of them.
What is a circular dependency and how do you fix it?
Bean A needs B and B needs A. With constructor injection Spring cannot create either and fails with BeanCurrentlyInCreationException; Spring Boot 2.6+ forbids circular references by default even for field injection. The real fix is a redesign: extract the shared logic into a third bean, or use events. A quick workaround is @Lazy on one constructor parameter.