← Home
☕Java Developer Interview Questions — Fresher to 5 YOEJava Dev InterviewNEW
🌱

Spring Core & DI

IoC container, beans, dependency injection · 13 questions

1

What is Inversion of Control (IoC), and what does the Spring IoC container do?

Must Know🌱 Fresher

Normally, an object creates and manages its own dependencies (new UserService(new UserRepository()) scattered everywhere). Inversion of Control flips this: instead of your code constructing and wiring dependencies, a container does it for you and injects them into your objects. The Spring IoC container reads configuration (annotations or XML), builds a graph of objects (beans), resolves which bean depends on which, and wires everything together before handing you a fully-assembled object.

🌱 Without IoC vs with IoC
Without IoC:
  class UserService {
    UserRepository repo = new UserRepository(); // UserService creates + controls its own dependency
  }

With IoC (Spring container):
  Container reads @Component/@Autowired metadata
       |
       v
  Creates UserRepository bean --> injects into --> UserService bean
  (UserService never calls "new" -- control is inverted to the container)
Spring CoreIoC
2

What is a Spring Bean?

Must Know🌱 Fresher

A bean is simply an object whose creation, configuration, and lifecycle are managed by the Spring IoC container instead of being manually instantiated with new. You mark a class as a candidate (@Component, @Service, @Repository, @Controller, or a @Bean-annotated factory method in a @Configuration class), and the container takes over creating it, injecting its dependencies, and — by default — keeping a single shared instance (the singleton scope) for the whole application.

Spring CoreBeans
3

What are the types of dependency injection in Spring?

Must Know🌱 Fresher
Constructor, setter, and field injectionjava
// Constructor injection (recommended)
@Service
class OrderService {
    private final PaymentClient paymentClient;
    OrderService(PaymentClient paymentClient) { this.paymentClient = paymentClient; }
}

// Setter injection
@Service
class OrderService {
    private PaymentClient paymentClient;
    @Autowired
    void setPaymentClient(PaymentClient paymentClient) { this.paymentClient = paymentClient; }
}

// Field injection (works, but discouraged -- see next question)
@Service
class OrderService {
    @Autowired
    private PaymentClient paymentClient;
}
Spring CoreDI
4

What are the bean scopes available in Spring?

Must Know🌱 Fresher
ScopeMeaning
singleton (default)One shared instance per Spring container, reused everywhere it's injected.
prototypeA brand-new instance every time the bean is requested/injected.
requestOne instance per HTTP request (web apps only).
sessionOne instance per HTTP session (web apps only).
applicationOne instance per ServletContext (effectively singleton for the whole web app).
Spring CoreBean Scopes
5

What is the difference between @Component, @Service, @Repository, and @Controller?

Must Know🌱 Fresher

All four are stereotype annotations — specializations of the generic @Component that mark a class as a Spring-managed bean, discovered via classpath scanning. Functionally, @Service and @Controller behave identically to plain @Component at the container level — the distinction is primarily semantic/documentation (this class is a business-logic service, this one's a web controller) so a reader instantly understands each class's role in the layered architecture.

@Repository is the one exception with real extra behavior: Spring automatically wraps its methods to translate database-specific exceptions into Spring's unified DataAccessException hierarchy, so calling code doesn't need to know which JDBC driver or ORM threw the original exception.

Spring CoreStereotypes
6

Why is constructor injection preferred over field injection?

Important📊 Mid
  • Immutability — constructor injection lets the field be final, guaranteeing it's set once and never null after construction; field injection can't be final.
  • Fails fast, at the right time — a missing/misconfigured dependency breaks object construction immediately (in tests too, with plain new), instead of surfacing later as a runtime NullPointerException the first time the field is used.
  • Testability — with constructor injection you can instantiate the class directly in a unit test and pass mocks, with zero Spring involved. Field injection forces you to use reflection or a Spring test context just to set a private field.
  • Surfaces design smells — a constructor with eight parameters is an obvious signal the class does too much; field injection hides that same problem.
Spring CoreDI
7

What is the lifecycle of a Spring bean?

Important📊 Mid
🔄 Spring bean lifecycle (simplified)
1. Container instantiates the bean (constructor runs)
2. Dependencies injected (constructor/setter/field)
3. Aware interfaces called if implemented (BeanNameAware, ApplicationContextAware...)
4. BeanPostProcessor.postProcessBeforeInitialization()
5. @PostConstruct method / InitializingBean.afterPropertiesSet() / custom init-method
6. BeanPostProcessor.postProcessAfterInitialization()   <- bean is now ready to use
        ... bean lives here, serving the application ...
7. Container shutdown: @PreDestroy / DisposableBean.destroy() / custom destroy-method
Spring CoreBean Lifecycle
8

What is the difference between ApplicationContext and BeanFactory?

Important🌱 Fresher

BeanFactory is the root, most basic container interface — lazy bean instantiation only, minimal features. ApplicationContext extends it and adds what real applications need: eager singleton instantiation at startup (fail fast on misconfiguration), event publishing, internationalization (message source), AOP integration, and easy access to environment properties. In practice, every Spring Boot application uses ApplicationContext (specifically AnnotationConfigApplicationContext or its web variant) — BeanFactory is rarely used directly today.

Spring Core
9

How do @Autowired, @Qualifier, and @Primary work together when multiple beans qualify?

Important📊 Mid

@Autowired tells Spring to inject a matching bean by type. If more than one bean implements that type, Spring needs a tiebreaker: @Primary marks one bean as the default choice whenever there's ambiguity; @Qualifier("beanName") lets the injection point explicitly pick a specific bean by name, overriding @Primary if both are present.

Resolving ambiguityjava
interface NotificationSender { }

@Primary @Component
class EmailSender implements NotificationSender { }

@Component("smsSender")
class SmsSender implements NotificationSender { }

@Service
class AlertService {
    AlertService(@Qualifier("smsSender") NotificationSender sender) { /* explicitly picks SMS */ }
}
Spring CoreDI
10

What do @Configuration and @Bean do?

Important🌱 Fresher

@Configuration marks a class as a source of bean definitions written in plain Java instead of XML. Each method inside it annotated @Bean returns an object that Spring registers as a managed bean — useful for wiring up third-party classes you don't own (so you can't add @Component to them) or beans that need custom construction logic.

Java-based configurationjava
@Configuration
class AppConfig {
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate(); // third-party class -- can't annotate it directly
    }
}
Spring CoreJava Config
11

What is Spring AOP, and what do aspect, advice, pointcut, and join point mean?

Important📊 Mid

Spring AOP (Aspect-Oriented Programming) lets you factor out cross-cutting concerns — logging, transaction management, security checks — that would otherwise be duplicated across many unrelated methods, and apply them declaratively instead.

  • Join point — a point during execution where an aspect could apply (in Spring AOP, always a method call).
  • Pointcut — an expression that selects which join points to match (e.g. "every public method in any @Service").
  • Advice — the actual code that runs at a matched join point, and when: @Before, @After, @Around (wraps the call, can short-circuit or modify the result), @AfterThrowing.
  • Aspect — a class (@Aspect) that bundles a pointcut with its advice.
A logging aspectjava
@Aspect @Component
class LoggingAspect {
    @Around("execution(* com.app.service.*.*(..))") // pointcut: any method in service package
    Object logTiming(ProceedingJoinPoint pjp) throws Throwable {
        long start = System.nanoTime();
        Object result = pjp.proceed(); // actually calls the real method
        log.info("{} took {}ms", pjp.getSignature(), (System.nanoTime() - start) / 1_000_000);
        return result;
    }
}

Spring's default AOP implementation works via proxies (a wrapper object intercepts calls), which is why AOP doesn't apply to private methods or self-invocation (a method calling another method on this bypasses the proxy).

Spring CoreAOP
12

What are Spring application events (@EventListener, ApplicationEventPublisher)?

Important📊 Mid

Spring's event mechanism lets beans communicate without holding a direct reference to each other — a publisher fires an event; any number of listeners react to it, fully decoupled from the code that raised it. It's Spring's built-in observer pattern.

Publishing and listening for a custom eventjava
record OrderPlacedEvent(Long orderId) { }

@Service
class OrderService {
    private final ApplicationEventPublisher publisher;
    void placeOrder(Order order) {
        // ... save the order ...
        publisher.publishEvent(new OrderPlacedEvent(order.getId()));
    }
}

@Component
class EmailNotifier {
    @EventListener
    void onOrderPlaced(OrderPlacedEvent event) {
        // send confirmation email -- runs decoupled from OrderService
    }
}

By default, listeners run synchronously, on the same thread and within the same transaction as the publisher — add @Async to a listener to run it on a separate thread, or @TransactionalEventListener to defer it until after the publishing transaction commits (useful so a listener never reacts to an event whose triggering transaction later rolled back).

Spring CoreEvents
13

How does Spring handle circular dependencies between beans?

Advanced📊 Mid

If Bean A's constructor needs Bean B, and Bean B's constructor needs Bean A, Spring can't fully construct either one first — with constructor injection, this is a hard failure at startup (BeanCurrentlyInCreationException), and the fix is almost always to redesign (extract the shared behavior into a third bean both depend on, or merge the two classes).

For singleton beans using setter/field injection, Spring can resolve the cycle: it creates A as a raw, not-yet-fully-initialized object, exposes that early reference to B while B is being constructed, then finishes populating A's fields — a workaround made possible by a three-level cache Spring maintains internally. It works, but most teams treat a circular dependency as a design smell to fix rather than a feature to rely on.

Spring CoreDI