
Spring Interview Questions and Answers
Spring Framework interviews can be intimidating, especially when you’re dealing with complex topics like dependency injection, AOP, and Spring Boot configurations. Whether you’re a seasoned developer looking to brush up on fundamentals or a system administrator working with Spring-based applications, understanding these core concepts is crucial for both landing that dream job and effectively managing Spring applications in production environments. This comprehensive guide covers the most frequently asked Spring interview questions, from basic IoC container concepts to advanced topics like microservices architecture, complete with practical examples and real-world scenarios you’ll actually encounter in your daily work.
Core Spring Framework Concepts
Let’s start with the fundamental questions that almost every Spring interview will cover. These aren’t just theoretical concepts – they’re the building blocks you’ll use every day.
Q: What is Inversion of Control (IoC) and how does Spring implement it?
IoC is a design principle where the control of object creation and dependency management is transferred from the application code to an external container. Spring implements IoC through its ApplicationContext and BeanFactory containers.
@Component
public class OrderService {
private final PaymentService paymentService;
private final InventoryService inventoryService;
// Constructor injection - Spring handles dependency creation
public OrderService(PaymentService paymentService,
InventoryService inventoryService) {
this.paymentService = paymentService;
this.inventoryService = inventoryService;
}
public void processOrder(Order order) {
inventoryService.reserveItems(order.getItems());
paymentService.processPayment(order.getTotal());
}
}
Q: Explain the different types of dependency injection in Spring.
Spring supports three main types of dependency injection:
- Constructor Injection: Dependencies are provided through class constructors (recommended approach)
- Setter Injection: Dependencies are provided through setter methods
- Field Injection: Dependencies are injected directly into fields using @Autowired
// Constructor Injection (Recommended)
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
// Setter Injection
@Service
public class EmailService {
private NotificationService notificationService;
@Autowired
public void setNotificationService(NotificationService notificationService) {
this.notificationService = notificationService;
}
}
// Field Injection (Not recommended for production)
@Service
public class ReportService {
@Autowired
private DataService dataService;
}
Bean Lifecycle and Scopes
Q: Describe the Spring Bean lifecycle.
Understanding the bean lifecycle is crucial for implementing initialization and cleanup logic properly. Here’s the complete lifecycle with practical examples:
@Component
public class DatabaseConnection implements InitializingBean, DisposableBean {
private Connection connection;
@PostConstruct
public void initConnection() {
System.out.println("@PostConstruct: Initializing database connection");
// Initialize connection pool
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean: After properties set");
// Additional initialization after all properties are set
}
@PreDestroy
public void cleanup() {
System.out.println("@PreDestroy: Cleaning up resources");
// Close connections, release resources
}
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean: Destroy method called");
// Final cleanup operations
}
}
Q: What are the different bean scopes in Spring?
Scope | Description | Use Case | Thread Safe |
---|---|---|---|
singleton | One instance per Spring container | Stateless services, repositories | Must be designed thread-safe |
prototype | New instance for each request | Stateful objects, temporary objects | Each instance is separate |
request | One instance per HTTP request | Web-specific data holders | Request-scoped |
session | One instance per HTTP session | User session data | Session-scoped |
application | One instance per ServletContext | Application-wide shared data | Must be thread-safe |
@Component
@Scope("prototype")
public class ShoppingCart {
private List<Item> items = new ArrayList<>();
public void addItem(Item item) {
items.add(item);
}
}
@Controller
@Scope(value = WebApplicationContext.SCOPE_SESSION,
proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UserSession {
private String userId;
private LocalDateTime loginTime;
public void initSession(String userId) {
this.userId = userId;
this.loginTime = LocalDateTime.now();
}
}
Spring Boot Configuration and Auto-Configuration
Q: How does Spring Boot auto-configuration work?
Spring Boot’s auto-configuration is one of its most powerful features, automatically configuring beans based on classpath dependencies and existing configurations. Here’s how it works under the hood:
// Custom auto-configuration example
@Configuration
@ConditionalOnClass(RedisTemplate.class)
@ConditionalOnProperty(name = "app.redis.enabled", havingValue = "true")
@EnableConfigurationProperties(RedisProperties.class)
public class CustomRedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RedisTemplate<String, Object> redisTemplate(
RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
return template;
}
}
// Enable auto-configuration in META-INF/spring.factories
// org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
// com.example.config.CustomRedisAutoConfiguration
Q: How do you create custom configuration properties?
// Configuration properties class
@ConfigurationProperties(prefix = "app.database")
@Data
public class DatabaseProperties {
private String url;
private String username;
private String password;
private Pool pool = new Pool();
@Data
public static class Pool {
private int maxSize = 10;
private int minSize = 5;
private Duration maxWait = Duration.ofSeconds(30);
}
}
// Configuration class
@Configuration
@EnableConfigurationProperties(DatabaseProperties.class)
public class DatabaseConfig {
@Bean
public DataSource customDataSource(DatabaseProperties properties) {
HikariConfig config = new HikariConfig();
config.setJdbcUrl(properties.getUrl());
config.setUsername(properties.getUsername());
config.setPassword(properties.getPassword());
config.setMaximumPoolSize(properties.getPool().getMaxSize());
config.setMinimumIdle(properties.getPool().getMinSize());
return new HikariDataSource(config);
}
}
Corresponding application.yml:
app:
database:
url: jdbc:postgresql://localhost:5432/mydb
username: ${DB_USER:admin}
password: ${DB_PASSWORD:secret}
pool:
max-size: 20
min-size: 5
max-wait: PT45S
Spring Data and JPA Integration
Q: How do you implement custom repository methods in Spring Data JPA?
This is a common real-world scenario where you need to go beyond basic CRUD operations:
// Custom repository interface
public interface CustomUserRepository {
List<User> findActiveUsersByDepartment(String department);
Page<User> findUsersWithComplexCriteria(UserSearchCriteria criteria, Pageable pageable);
}
// Custom repository implementation
@Repository
public class CustomUserRepositoryImpl implements CustomUserRepository {
@PersistenceContext
private EntityManager entityManager;
@Override
public List<User> findActiveUsersByDepartment(String department) {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<User> query = cb.createQuery(User.class);
Root<User> user = query.from(User.class);
List<Predicate> predicates = new ArrayList<>();
predicates.add(cb.equal(user.get("department"), department));
predicates.add(cb.equal(user.get("active"), true));
query.where(predicates.toArray(new Predicate[0]));
return entityManager.createQuery(query).getResultList();
}
@Override
public Page<User> findUsersWithComplexCriteria(UserSearchCriteria criteria,
Pageable pageable) {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<User> query = cb.createQuery(User.class);
Root<User> user = query.from(User.class);
List<Predicate> predicates = buildPredicates(cb, user, criteria);
query.where(predicates.toArray(new Predicate[0]));
TypedQuery<User> typedQuery = entityManager.createQuery(query);
typedQuery.setFirstResult((int) pageable.getOffset());
typedQuery.setMaxResults(pageable.getPageSize());
List<User> results = typedQuery.getResultList();
long total = getTotalCount(criteria);
return new PageImpl<>(results, pageable, total);
}
}
// Main repository interface extending both JpaRepository and custom interface
public interface UserRepository extends JpaRepository<User, Long>, CustomUserRepository {
@Query("SELECT u FROM User u WHERE u.email = ?1 AND u.active = true")
Optional<User> findActiveUserByEmail(String email);
@Modifying
@Query("UPDATE User u SET u.lastLoginDate = :loginDate WHERE u.id = :userId")
int updateLastLoginDate(@Param("userId") Long userId,
@Param("loginDate") LocalDateTime loginDate);
}
Aspect-Oriented Programming (AOP)
Q: Implement a logging aspect that captures method execution time and parameters.
AOP is essential for cross-cutting concerns like logging, security, and transaction management:
@Aspect
@Component
@Slf4j
public class LoggingAspect {
@Pointcut("@annotation(com.example.annotation.Loggable)")
public void loggableMethods() {}
@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceMethods() {}
@Around("loggableMethods() || serviceMethods()")
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
String methodName = joinPoint.getSignature().getName();
String className = joinPoint.getTarget().getClass().getSimpleName();
// Log method entry with parameters
Object[] args = joinPoint.getArgs();
log.info("Entering method: {}.{} with arguments: {}",
className, methodName, Arrays.toString(args));
long startTime = System.currentTimeMillis();
Object result = null;
try {
result = joinPoint.proceed();
long executionTime = System.currentTimeMillis() - startTime;
log.info("Method: {}.{} executed successfully in {} ms",
className, methodName, executionTime);
return result;
} catch (Exception e) {
long executionTime = System.currentTimeMillis() - startTime;
log.error("Method: {}.{} failed after {} ms with exception: {}",
className, methodName, executionTime, e.getMessage());
throw e;
}
}
@AfterThrowing(pointcut = "serviceMethods()", throwing = "exception")
public void logException(JoinPoint joinPoint, Throwable exception) {
String methodName = joinPoint.getSignature().getName();
String className = joinPoint.getTarget().getClass().getSimpleName();
log.error("Exception in method: {}.{} - {}",
className, methodName, exception.getMessage(), exception);
}
}
// Custom annotation for selective logging
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Loggable {
boolean logParams() default true;
boolean logResult() default false;
}
// Usage example
@Service
public class OrderService {
@Loggable(logParams = true, logResult = true)
public Order processOrder(OrderRequest request) {
// Business logic here
return new Order(request);
}
public void sendNotification(String email) {
// This will be logged due to serviceMethods() pointcut
}
}
Spring Security Implementation
Q: How do you implement JWT-based authentication in Spring Security?
Here’s a complete JWT implementation that you’ll commonly encounter in microservices architectures:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
@Autowired
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
@Autowired
private JwtRequestFilter jwtRequestFilter;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public AuthenticationManager authenticationManager(
AuthenticationConfiguration config) throws Exception {
return config.getAuthenticationManager();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeHttpRequests(authz -> authz
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/api/public/**").permitAll()
.requestMatchers(HttpMethod.GET, "/api/products/**").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint)
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}
@Component
public class JwtRequestFilter extends OncePerRequestFilter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtUtil jwtUtil;
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain) throws ServletException, IOException {
final String requestTokenHeader = request.getHeader("Authorization");
String username = null;
String jwtToken = null;
if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {
jwtToken = requestTokenHeader.substring(7);
try {
username = jwtUtil.getUsernameFromToken(jwtToken);
} catch (IllegalArgumentException e) {
logger.error("Unable to get JWT Token");
} catch (ExpiredJwtException e) {
logger.error("JWT Token has expired");
}
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (jwtUtil.validateToken(jwtToken, userDetails)) {
UsernamePasswordAuthenticationToken authToken =
new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authToken);
}
}
chain.doFilter(request, response);
}
}
Microservices and Spring Cloud
Q: How do you implement service discovery and load balancing with Spring Cloud?
Modern Spring applications often run in distributed environments where service discovery is crucial:
// Eureka Server Configuration
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
// Eureka Server application.yml
server:
port: 8761
eureka:
instance:
hostname: localhost
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
// Client Service Configuration
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}
// Feign Client for inter-service communication
@FeignClient(name = "inventory-service", fallback = InventoryServiceFallback.class)
public interface InventoryServiceClient {
@GetMapping("/api/inventory/check/{productId}")
InventoryResponse checkInventory(@PathVariable("productId") Long productId);
@PostMapping("/api/inventory/reserve")
ReservationResponse reserveItems(@RequestBody ReservationRequest request);
}
// Fallback implementation for circuit breaker
@Component
public class InventoryServiceFallback implements InventoryServiceClient {
@Override
public InventoryResponse checkInventory(Long productId) {
return InventoryResponse.builder()
.productId(productId)
.available(false)
.message("Inventory service is currently unavailable")
.build();
}
@Override
public ReservationResponse reserveItems(ReservationRequest request) {
return ReservationResponse.builder()
.success(false)
.message("Unable to reserve items - service unavailable")
.build();
}
}
// Circuit Breaker with Resilience4j
@RestController
@RequiredArgsConstructor
public class OrderController {
private final InventoryServiceClient inventoryClient;
@PostMapping("/api/orders")
@CircuitBreaker(name = "inventory-service", fallbackMethod = "fallbackCreateOrder")
@TimeLimiter(name = "inventory-service")
@Retry(name = "inventory-service")
public CompletableFuture<ResponseEntity<OrderResponse>> createOrder(
@RequestBody OrderRequest request) {
return CompletableFuture.supplyAsync(() -> {
InventoryResponse inventory = inventoryClient.checkInventory(request.getProductId());
if (inventory.isAvailable()) {
// Process order logic
OrderResponse response = processOrder(request);
return ResponseEntity.ok(response);
} else {
return ResponseEntity.badRequest()
.body(OrderResponse.error("Product not available"));
}
});
}
public CompletableFuture<ResponseEntity<OrderResponse>> fallbackCreateOrder(
OrderRequest request, Exception ex) {
return CompletableFuture.completedFuture(
ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE)
.body(OrderResponse.error("Service temporarily unavailable"))
);
}
}
Testing Strategies
Q: How do you write effective integration tests for Spring applications?
Testing is crucial for maintaining reliable Spring applications, especially in production environments:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Testcontainers
class OrderServiceIntegrationTest {
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:14")
.withDatabaseName("testdb")
.withUsername("test")
.withPassword("test");
@Container
static GenericContainer<?> redis = new GenericContainer<>("redis:7-alpine")
.withExposedPorts(6379);
@Autowired
private TestRestTemplate restTemplate;
@Autowired
private OrderRepository orderRepository;
@MockBean
private PaymentService paymentService;
@DynamicPropertySource
static void configureProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.datasource.username", postgres::getUsername);
registry.add("spring.datasource.password", postgres::getPassword);
registry.add("spring.redis.host", redis::getHost);
registry.add("spring.redis.port", redis::getFirstMappedPort);
}
@Test
@Transactional
@Rollback
void shouldCreateOrderSuccessfully() {
// Given
OrderRequest request = OrderRequest.builder()
.customerId(1L)
.productId(100L)
.quantity(2)
.build();
when(paymentService.processPayment(any())).thenReturn(
PaymentResponse.success("payment-123")
);
// When
ResponseEntity<OrderResponse> response = restTemplate.postForEntity(
"/api/orders", request, OrderResponse.class
);
// Then
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.CREATED);
assertThat(response.getBody().getOrderId()).isNotNull();
Optional<Order> savedOrder = orderRepository.findById(response.getBody().getOrderId());
assertThat(savedOrder).isPresent();
assertThat(savedOrder.get().getStatus()).isEqualTo(OrderStatus.CONFIRMED);
}
@Test
void shouldHandlePaymentFailureGracefully() {
// Given
OrderRequest request = OrderRequest.builder()
.customerId(1L)
.productId(100L)
.quantity(2)
.build();
when(paymentService.processPayment(any())).thenThrow(
new PaymentException("Insufficient funds")
);
// When
ResponseEntity<OrderResponse> response = restTemplate.postForEntity(
"/api/orders", request, OrderResponse.class
);
// Then
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST);
assertThat(response.getBody().getError()).contains("Payment failed");
}
}
// Unit test with Spring Test Context
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {OrderService.class})
@MockBean({PaymentService.class, InventoryService.class, OrderRepository.class})
class OrderServiceTest {
@Autowired
private OrderService orderService;
@MockBean
private PaymentService paymentService;
@MockBean
private InventoryService inventoryService;
@MockBean
private OrderRepository orderRepository;
@Test
void shouldProcessOrderWithValidInventory() {
// Given
Order order = createTestOrder();
when(inventoryService.checkAvailability(anyLong(), anyInt())).thenReturn(true);
when(paymentService.processPayment(any())).thenReturn(PaymentResponse.success("123"));
when(orderRepository.save(any())).thenReturn(order);
// When
OrderResponse result = orderService.processOrder(createOrderRequest());
// Then
assertThat(result.getOrderId()).isEqualTo(order.getId());
verify(inventoryService).reserveItems(order.getProductId(), order.getQuantity());
verify(paymentService).processPayment(any());
}
}
Performance Optimization and Best Practices
Q: How do you optimize Spring Boot application performance?
Performance optimization is critical for production deployments, especially when running on VPS or dedicated servers:
- Database Connection Pooling: Configure HikariCP properly for your workload
- Caching Strategy: Implement multi-level caching with Redis and Spring Cache
- JVM Tuning: Optimize garbage collection and memory settings
- Lazy Loading: Use @Lazy annotations and lazy initialization
- Async Processing: Implement asynchronous methods for heavy operations
// Database optimization configuration
@Configuration
public class DatabaseOptimizationConfig {
@Bean
@ConfigurationProperties("app.datasource.hikari")
public HikariConfig hikariConfig() {
HikariConfig config = new HikariConfig();
config.setMaximumPoolSize(20);
config.setMinimumIdle(5);
config.setConnectionTimeout(30000);
config.setIdleTimeout(600000);
config.setMaxLifetime(1800000);
config.setLeakDetectionThreshold(60000);
return config;
}
@Bean
public DataSource dataSource() {
return new HikariDataSource(hikariConfig());
}
}
// Caching configuration
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(1))
.serializeKeysWith(RedisSerializationContext.SerializationPair
.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair
.fromSerializer(new GenericJackson2JsonRedisSerializer()));
return RedisCacheManager.builder(connectionFactory)
.cacheDefaults(config)
.build();
}
}
// Service with optimized caching and async processing
@Service
@Slf4j
public class ProductService {
@Cacheable(value = "products", key = "#productId")
public Product getProduct(Long productId) {
log.info("Fetching product from database: {}", productId);
return productRepository.findById(productId)
.orElseThrow(() -> new ProductNotFoundException(productId));
}
@CacheEvict(value = "products", key = "#product.id")
public Product updateProduct(Product product) {
return productRepository.save(product);
}
@Async("taskExecutor")
@EventListener
public CompletableFuture<Void> handleProductUpdated(ProductUpdatedEvent event) {
log.info("Processing product update asynchronously: {}", event.getProductId());
// Heavy processing like updating search indexes, sending notifications
updateSearchIndex(event.getProductId());
sendNotifications(event);
return CompletableFuture.completedFuture(null);
}
}
// Async configuration
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean("taskExecutor")
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(4);
executor.setMaxPoolSize(16);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("async-task-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}
Common Pitfalls and Troubleshooting
Q: What are the most common Spring Boot issues and how do you debug them?
Here are the issues you’ll encounter most frequently in production environments:
Issue | Symptoms | Solution | Prevention |
---|---|---|---|
Circular Dependencies | BeanCurrentlyInCreationException | Use @Lazy, refactor design | Proper dependency design |
N+1 Query Problem | Poor performance, many SQL queries | Use @EntityGraph, JOIN FETCH | Query optimization reviews |
Memory Leaks | OutOfMemoryError, increasing heap usage | Profile with JProfiler, fix resource leaks | Proper resource management |
Transaction Issues | Data inconsistency, rollback failures | Proper @Transactional usage | Transaction boundary design |
// Common debugging configuration
@Configuration
public class DebuggingConfig {
// Enable SQL logging for development
@Bean
@Profile("dev")
public Logger sqlLogger() {
Logger logger = (Logger) LoggerFactory.getLogger("org.hibernate.SQL");
logger.setLevel(Level.DEBUG);
return logger;
}
// Health check endpoint
@Component
public class CustomHealthIndicator implements HealthIndicator {
@Autowired
private DataSource dataSource;
@Override
public Health health() {
try (Connection connection = dataSource.getConnection()) {
if (connection.isValid(1000)) {
return Health.up()
.withDetail("database", "Available")
.withDetail("connection_pool", getPoolStatus())
.build();
}
} catch (SQLException e) {
return Health.down()
.withDetail("database", "Unavailable")
.withException(e)
.build();
}
return Health.down().withDetail("database", "Unknown").build();
}
}
}
// Debugging utilities
@RestController
@Profile({"dev", "staging"})
public class DebugController {
@Autowired
private ApplicationContext applicationContext;
@GetMapping("/debug/beans")
public Map<String, Object> getBeans() {
return Arrays.stream(applicationContext.getBeanDefinitionNames())
.collect(Collectors.toMap(
name -> name,
name -> applicationContext.getBean(name).getClass().getSimpleName()
));
}
@GetMapping("/debug/memory")
public Map<String, Long> getMemoryInfo() {
Runtime runtime = Runtime.getRuntime();
Map<String, Long> memoryInfo = new HashMap<>();
memoryInfo.put("totalMemory", runtime.totalMemory());
memoryInfo.put("freeMemory", runtime.freeMemory());
memoryInfo.put("usedMemory", runtime.totalMemory() - runtime.freeMemory());
memoryInfo.put("maxMemory", runtime.maxMemory());
return memoryInfo;
}
}
Understanding these Spring concepts thoroughly will not only help you ace interviews but also build robust, scalable applications in production. Remember that interviewers often ask follow-up questions about real-world scenarios, so always be prepared to explain how you’ve used these concepts in actual projects. Practice implementing these examples in your development environment, and don’t forget to check the official Spring Guides for the latest best practices and updates.
The key to succeeding in Spring interviews is combining theoretical knowledge with practical experience. Focus on understanding the underlying principles, practice with real code examples, and be ready to discuss performance implications and production considerations. Whether you’re deploying on cloud platforms or managing your own infrastructure, these concepts form the foundation of professional Spring development.

This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.
This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.