1️⃣ Core Spring
What is Spring Framework?
Answer:
-
Lightweight, open-source Java framework for enterprise applications
-
Based on IoC (Inversion of Control) and DI (Dependency Injection)
-
Promotes loose coupling and testability
-
Modular architecture (Core, AOP, JDBC, ORM, MVC, Security)
-
Eliminates heavy XML configuration (supports annotations & Java config)
Real-time example:
-
In a banking app → Service layer depends on Repository
-
Spring injects repository into service automatically
What is Inversion of Control (IoC)?
Answer:
-
Control of object creation is given to Spring container
-
Developer no longer uses
newkeyword for dependencies -
Container manages:
-
Bean creation
-
Dependency wiring
-
Lifecycle
-
Configuration
-
Without IoC:
UserService service = new UserService();
With IoC:
@Autowired
UserService service;
Real-time example:
-
Large e-commerce app → 200+ services
-
IoC avoids manual object creation chaos
What is Dependency Injection (DI)?
Answer:
-
Technique to inject required dependencies into a class
-
Achieves loose coupling
-
Makes unit testing easier
Types of DI
-
Constructor Injection (Recommended)
-
Setter Injection
-
Field Injection (Avoid in production)
Why Constructor Injection?
-
Makes dependencies mandatory
-
Supports immutability
-
Easy for unit testing (Mockito)
Example:
@Service
class OrderService {
private final PaymentService paymentService;
public OrderService(PaymentService paymentService) {
this.paymentService = paymentService;
}
}
Real-time example:
-
OrderService depends on PaymentService
-
Spring injects automatically
What is a Spring Bean?
Answer:
-
Any object managed by Spring IoC container
-
Created, configured, and destroyed by container
Ways to define beans
-
@Component -
@Service -
@Repository -
@Controller -
@Bean(Java config) -
XML configuration (legacy)
Real-time example:
-
UserService
-
EmailService
-
ProductRepository
What is Spring Bean Scopes?
Spring defines lifecycle and visibility of beans.
1. Singleton (Default)
-
One instance per Spring container
-
Shared across entire application
-
Thread-safe design required
Used in:
-
Service layer
-
DAO layer
-
Utility classes
Example:
@Scope("singleton")
@Service
class UserService {}
Real-time:
-
PaymentService shared by all users
2. Prototype
-
New object every time requested
-
Spring manages creation only (not destruction)
-
Suitable for stateful objects
Used in:
-
Report generator
-
Temporary calculation objects
@Scope("prototype")
@Component
class ReportBuilder {}
3. Request Scope (Web Apps)
-
One bean per HTTP request
-
Destroyed after request completes
Used in:
-
Request-specific form data
-
API request context
4. Session Scope
-
One bean per HTTP session
-
Lives until session expires
Used in:
-
Shopping cart
-
Logged-in user details
5. Application Scope
-
One per ServletContext
-
Shared across entire web application
Used in:
-
Application cache
-
Global settings
6. WebSocket Scope
-
One bean per WebSocket session
-
Used in chat applications
Scope Interview Follow-up Points
-
Singleton is NOT same as GoF Singleton
-
Singleton beans must be stateless
-
Prototype injected into Singleton → creates problem (use ObjectFactory)
What is @Component, @Service, @Repository, @Controller?
Answer:
All are stereotype annotations.
-
@Component→ Generic bean -
@Service→ Business logic -
@Repository→ DAO (adds exception translation) -
@Controller→ MVC controller
Real-time:
-
Layered architecture separation
What is @Autowired?
Answer:
-
Automatically injects dependency
-
Works on constructor, setter, field
-
By default injects by type
-
Use
@Qualifierif multiple beans
Example:
@Autowired
@Qualifier("stripePayment")
PaymentService paymentService;
What is Spring AOP?
Answer:
Aspect-Oriented Programming separates cross-cutting concerns.
Cross-cutting concerns:
-
Logging
-
Security
-
Transaction management
-
Monitoring
Key Terms:
-
Aspect → LoggingAspect
-
Advice → Before, After, Around
-
JoinPoint → Method execution
-
Pointcut → Expression
Example:
@Aspect
@Component
class LoggingAspect {
@Before("execution(* com.app.service.*.*(..))")
public void log() {
System.out.println("Method called");
}
}
Real-time:
-
Logging every service method without modifying code
What is Bean Lifecycle?
Phases:
-
Bean instantiation
-
Dependency injection
-
@PostConstruct -
Ready for use
-
@PreDestroy -
Destroy
Customization:
-
InitializingBean
-
DisposableBean
Real-time:
-
Opening DB connection on init
-
Closing resources on destroy
What is BeanFactory vs ApplicationContext?
What is @Configuration and @Bean?
Answer:
-
@Configuration→ Marks config class -
@Bean→ Defines custom bean
Example:
@Configuration
class AppConfig {
@Bean
public ModelMapper modelMapper() {
return new ModelMapper();
}
}
Real-time:
-
Third-party libraries as beans
What is Circular Dependency?
Answer:
A circular dependency occurs when:
-
Bean A depends on Bean B
-
Bean B depends on Bean A
This creates a dependency cycle.
Example (Constructor Injection – Fails)
@Service
class A {
private final B b;
public A(B b) {
this.b = b;
}
}
@Service
class B {
private final A a;
public B(A a) {
this.a = a;
}
}
Result:
-
Spring tries to create A → needs B
-
To create B → needs A
-
Fails with
BeanCurrentlyInCreationException
Setter Injection – Works (Not Recommended)
@Service
class A {
private B b;
@Autowired
public void setB(B b) {
this.b = b;
}
}
@Service
class B {
private A a;
@Autowired
public void setA(A a) {
this.a = a;
}
}
Why it works:
-
Spring first creates beans without dependencies
-
Injects dependencies afterward
-
Breaks creation cycle
Why not recommended:
-
Hides poor design
-
Allows partially initialized beans
-
Encourages tight coupling
-
Makes dependencies optional (not enforced)
Proper Solution (Refactor Design)
Instead of A and B depending on each other, extract common logic into a third service.
Refactored Design
@Service
class CommonService {
}
@Service
class A {
private final CommonService commonService;
public A(CommonService commonService) {
this.commonService = commonService;
}
}
@Service
class B {
private final CommonService commonService;
public B(CommonService commonService) {
this.commonService = commonService;
}
}
Now:
-
A → CommonService
-
B → CommonService
-
No circular dependency
Interview Summary
-
Circular dependency = two beans depend on each other
-
Constructor injection fails
-
Setter injection works but is bad design
-
Best solution → redesign architecture and remove tight coupling
What is Profiles in Spring?
Answer:
-
Used for environment-specific configuration
-
Allows different beans and properties to be loaded based on the active environment
-
Helps separate configuration without changing code
-
Common real-time environment names:
-
local
-
dev
-
qa
-
uat
-
staging
-
prod
-
Example Using @Profile
@Profile("dev")
@Component
class DevDataSource {
}
@Profile("prod")
@Component
class ProdDataSource {
}
Only the bean matching the active profile will be loaded.
How to Activate Profile
In application.properties
spring.profiles.active=dev
Or via command line
--spring.profiles.active=prod
Profile-Specific Property Files
-
application-local.properties
-
application-dev.properties
-
application-qa.properties
-
application-uat.properties
-
application-staging.properties
-
application-prod.properties
Spring automatically loads the correct file based on the active profile.
Real-Time Example
-
local → Developer machine DB
-
dev → Shared development database
-
qa → QA testing database
-
uat → User acceptance testing environment
-
staging → Pre-production environment
-
prod → Production database
Interview Summary
Profiles allow loading environment-specific beans and configurations such as database URLs, logging levels, API keys, and feature flags without modifying application code.
What is @Value and @PropertySource?
Answer:
-
Used to inject values from properties files
-
@Value→ Injects a specific property value -
@PropertySource→ Loads external/custom property files into Spring context
Example using @Value
@Value("${server.port}")
private int port;
Injecting custom property:
@Value("${app.name}")
private String appName;
Example using @PropertySource
@Configuration
@PropertySource("classpath:custom.properties")
class AppConfig {
}
This loads custom.properties so values can be injected using @Value.
Used In
-
Database configuration
-
API keys
-
External service URLs
-
Feature flags
Interview Summary
@Value is used to inject individual property values, while @PropertySource is used to load additional properties files into the Spring application context.
What is Environment Abstraction?
Answer:
-
Provides access to application properties
-
Gives access to active profiles
-
Allows reading system environment variables
-
Supports checking default profiles
-
Helps implement environment-based logic
Spring provides the Environment interface for this.
Example using Environment
@Autowired
private Environment env;
Read property
String dbUrl = env.getProperty("spring.datasource.url");
Get active profiles
String[] profiles = env.getActiveProfiles();
Get default profiles
String[] defaultProfiles = env.getDefaultProfiles();
Read system environment variable
String javaHome = env.getProperty("JAVA_HOME");
Check if profile is active
if (env.acceptsProfiles("prod")) {
System.out.println("Production environment");
}
Used In
-
Dynamic configuration access
-
Profile-based conditional logic
-
Reading OS environment variables
-
Feature toggles based on environment
Interview Summary
Environment abstraction allows accessing properties, profiles, and system variables programmatically using the Environment interface, enabling environment-aware application behavior.
What is Lazy Initialization?
Answer:
-
@Lazy→ Bean is created only when it is first requested -
Default singleton beans are created eagerly at startup
-
Helps reduce application startup time
-
Useful for heavy or rarely used beans
Example using @Lazy
@Lazy
@Service
class HeavyService {
}
Bean will be created only when it is first injected or accessed.
Using @Lazy on Injection
@Service
class OrderService {
private final HeavyService heavyService;
public OrderService(@Lazy HeavyService heavyService) {
this.heavyService = heavyService;
}
}
Here, HeavyService is initialized only when actually used.
Used In
-
Expensive initialization logic
-
Large configuration objects
-
Rarely used services
-
Improving startup performance
Interview Summary
Lazy initialization delays bean creation until it is needed, helping optimize startup time and resource usage.