Skip to content

Spring Common Questions

Spring Core

Q1: What is Inversion of Control (IoC)?

IoC is a design principle where object creation and lifecycle management is delegated to a container instead of being controlled by application code.

// Without IoC - Application controls
public class OrderService {
    private PaymentService payment = new StripePaymentService();  // Tight coupling
}

// With IoC - Container controls
@Service
public class OrderService {
    private final PaymentService payment;  // Injected by container

    public OrderService(PaymentService payment) {
        this.payment = payment;
    }
}

Benefits: Loose coupling, testability, flexibility, single responsibility.


Q2: Constructor vs Setter vs Field Injection?

// Constructor (RECOMMENDED)
@Service
public class OrderService {
    private final PaymentService paymentService;

    public OrderService(PaymentService paymentService) {
        this.paymentService = paymentService;
    }
}

// Setter (for optional dependencies)
@Service
public class NotificationService {
    private SmsService smsService;

    @Autowired(required = false)
    public void setSmsService(SmsService smsService) {
        this.smsService = smsService;
    }
}

// Field (AVOID)
@Service
public class UserService {
    @Autowired
    private UserRepository repository;  // Hard to test!
}
Aspect Constructor Setter Field
Immutability Yes (final) No No
Testability Easy Medium Hard
Optional deps No Yes Yes
Circular deps Fails fast Allows Allows

Q3: What are Bean Scopes?

@Component
@Scope("singleton")    // Default - one per container
@Scope("prototype")    // New instance each request
@Scope("request")      // One per HTTP request
@Scope("session")      // One per HTTP session

Prototype in Singleton Problem:

@Service  // Singleton
public class OrderService {
    @Autowired
    private ShoppingCart cart;  // Prototype - WRONG! Same instance always

    // Solution: Use ObjectFactory
    @Autowired
    private ObjectFactory<ShoppingCart> cartFactory;

    public void checkout() {
        ShoppingCart cart = cartFactory.getObject();  // New instance
    }
}


Q4: @Component vs @Bean?

// @Component - Class-level, auto-detected via component scanning
@Component
public class MyService { }

// @Bean - Method-level in @Configuration, for third-party classes
@Configuration
public class AppConfig {
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

Q5: Bean Lifecycle Callbacks?

@Service
public class CacheService {

    @PostConstruct  // After dependency injection
    public void init() {
        loadCache();
    }

    @PreDestroy  // Before destruction
    public void cleanup() {
        persistCache();
    }
}

Order: Constructor → DI → @PostConstruct → afterPropertiesSet → init-method


Spring Boot

Q6: What is @SpringBootApplication?

Combines three annotations:

@SpringBootApplication  // Equivalent to:
@Configuration          // Configuration class
@EnableAutoConfiguration // Enable auto-configuration
@ComponentScan          // Scan current package + subpackages
public class Application { }


Q7: How does Auto-Configuration work?

  1. @EnableAutoConfiguration triggers scanning
  2. Reads META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  3. Each auto-config has @Conditional annotations:
    @Configuration
    @ConditionalOnClass(DataSource.class)        // Class on classpath
    @ConditionalOnMissingBean(DataSource.class)  // No existing bean
    public class DataSourceAutoConfiguration {
        @Bean
        public DataSource dataSource() { }
    }
    
  4. Your custom beans take precedence (@ConditionalOnMissingBean)

Q8: Externalized Configuration Priority?

  1. Command line args (--server.port=9000)
  2. Java system properties (-Dserver.port=9000)
  3. OS environment variables (SERVER_PORT=9000)
  4. Profile-specific properties (application-prod.yml)
  5. Application properties (application.yml)

Q9: How to create a Custom Starter?

  1. Create auto-configuration class:

    @Configuration
    @ConditionalOnClass(MyService.class)
    @EnableConfigurationProperties(MyProperties.class)
    public class MyAutoConfiguration {
        @Bean
        @ConditionalOnMissingBean
        public MyService myService(MyProperties props) {
            return new MyService(props);
        }
    }
    

  2. Register in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

  3. Create starter module with dependencies


Spring MVC

Q10: Request Processing Flow?

Request → DispatcherServlet → HandlerMapping → Interceptor.preHandle
       → Controller → Interceptor.postHandle → ViewResolver → View → Response

Q11: @Controller vs @RestController?

@Controller  // Returns view name
public class WebController {
    @GetMapping("/page")
    public String page(Model model) {
        return "page";  // View name
    }
}

@RestController  // @Controller + @ResponseBody
public class ApiController {
    @GetMapping("/api/data")
    public Data getData() {
        return new Data();  // Serialized to JSON
    }
}

Q12: Exception Handling?

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ResourceNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ErrorResponse handleNotFound(ResourceNotFoundException ex) {
        return new ErrorResponse("NOT_FOUND", ex.getMessage());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ErrorResponse handleValidation(MethodArgumentNotValidException ex) {
        return new ErrorResponse("VALIDATION_ERROR", getErrors(ex));
    }
}

Spring Data JPA

Q13: JpaRepository vs CrudRepository?

Method CrudRepository JpaRepository
save
findById
findAll ✓ (Iterable) ✓ (List)
flush
saveAndFlush
deleteInBatch
getReferenceById

Q14: N+1 Problem?

Problem: Loading parent entities causes N additional queries for children.

List<Order> orders = orderRepository.findAll();  // 1 query
for (Order o : orders) {
    o.getItems().size();  // N queries!
}

Solutions:

// 1. JOIN FETCH
@Query("SELECT o FROM Order o JOIN FETCH o.items")
List<Order> findAllWithItems();

// 2. @EntityGraph
@EntityGraph(attributePaths = {"items"})
List<Order> findAll();

// 3. @BatchSize on entity
@OneToMany
@BatchSize(size = 50)
private List<OrderItem> items;


Q15: Lazy vs Eager Loading?

@ManyToOne(fetch = FetchType.LAZY)   // Load on access (default for collections)
@ManyToOne(fetch = FetchType.EAGER)  // Load immediately (default for single)

LazyInitializationException: Accessing lazy-loaded entity outside session. Solution: Keep session open, use JOIN FETCH, or use DTO projection.


Q16: @Transactional Best Practices?

@Transactional(
    readOnly = true,              // Optimize for reads
    propagation = REQUIRED,       // Use existing or create new
    isolation = READ_COMMITTED,   // Prevent dirty reads
    timeout = 30,                 // Timeout in seconds
    rollbackFor = BusinessException.class  // Rollback for checked
)
public void process() { }

Common pitfalls: - Self-invocation bypasses proxy - Checked exceptions don't rollback by default - readOnly doesn't prevent writes (just hints)


Q17: Optimistic vs Pessimistic Locking?

// Optimistic - @Version field
@Entity
public class Order {
    @Version
    private Long version;  // Auto-incremented on update
}

// Pessimistic - Database lock
@Lock(LockModeType.PESSIMISTIC_WRITE)
Optional<Order> findById(Long id);
Aspect Optimistic Pessimistic
Concurrency High Low
Conflicts Detect at commit Prevent
Use case Read-heavy Write-heavy

Spring Security

Q18: Security Filter Chain?

Request → CorsFilter → CsrfFilter → AuthenticationFilter
       → AuthorizationFilter → Controller
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    return http
        .csrf(csrf -> csrf.disable())
        .authorizeHttpRequests(auth -> auth
            .requestMatchers("/public/**").permitAll()
            .requestMatchers("/admin/**").hasRole("ADMIN")
            .anyRequest().authenticated()
        )
        .oauth2ResourceServer(oauth2 -> oauth2.jwt())
        .build();
}

Q19: JWT vs Session Authentication?

Aspect JWT Session
Storage Client (token) Server
Scalability Stateless Requires sticky sessions
Revocation Difficult Easy
Size Larger Cookie ID only

Q20: @PreAuthorize vs @Secured?

// @PreAuthorize - SpEL expressions, more flexible
@PreAuthorize("hasRole('ADMIN') or #userId == authentication.principal.id")
public User getUser(Long userId) { }

// @Secured - Simple role check
@Secured("ROLE_ADMIN")
public void adminOnly() { }

AOP

Q21: What is AOP?

Aspect-Oriented Programming modularizes cross-cutting concerns (logging, security, transactions).

@Aspect
@Component
public class LoggingAspect {

    @Around("execution(* com.example.service.*.*(..))")
    public Object logMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("Entering: {}", joinPoint.getSignature());
        Object result = joinPoint.proceed();
        log.info("Exiting: {}", joinPoint.getSignature());
        return result;
    }
}

Terms: Aspect, Join Point, Advice, Pointcut, Weaving


Q22: Spring AOP vs AspectJ?

Aspect Spring AOP AspectJ
Weaving Runtime (proxy) Compile/Load time
Join points Method only Methods, fields, constructors
Performance Slower Faster
Complexity Simpler More complex
Self-invocation Not intercepted Intercepted

Q23: Self-Invocation Problem?

@Service
public class OrderService {

    @Transactional
    public void processOrder() {
        validateOrder();  // NOT transactional! Direct call
    }

    @Transactional(propagation = REQUIRES_NEW)
    public void validateOrder() { }
}

Solutions: 1. Inject self: @Autowired private OrderService self; 2. Use AopContext.currentProxy() 3. Extract to separate service


Testing

Q24: @SpringBootTest vs @WebMvcTest?

// Full application context
@SpringBootTest(webEnvironment = RANDOM_PORT)
class IntegrationTest {
    @Autowired
    private TestRestTemplate restTemplate;
}

// Web layer only
@WebMvcTest(UserController.class)
class ControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private UserService userService;
}

// Repository layer only
@DataJpaTest
class RepositoryTest {
    @Autowired
    private UserRepository repository;
}

Q25: How to test secured endpoints?

@WebMvcTest(OrderController.class)
class SecuredControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    @WithMockUser(roles = "ADMIN")
    void adminCanAccess() throws Exception {
        mockMvc.perform(get("/admin/orders"))
            .andExpect(status().isOk());
    }

    @Test
    void unauthenticatedDenied() throws Exception {
        mockMvc.perform(get("/admin/orders"))
            .andExpect(status().isUnauthorized());
    }
}

Performance & Best Practices

Q26: How to improve Spring Boot startup time?

  1. Use lazy initialization: spring.main.lazy-initialization=true
  2. Exclude unused auto-configurations
  3. Use Spring AOT (Ahead-of-Time compilation)
  4. Profile startup: spring.application.admin.enabled=true
  5. Use GraalVM native image

Q27: Connection Pool Configuration?

spring:
  datasource:
    hikari:
      minimum-idle: 5
      maximum-pool-size: 20
      idle-timeout: 300000
      pool-name: HikariPool
      max-lifetime: 1800000
      connection-timeout: 20000

Q28: Caching Strategies?

@EnableCaching
@Configuration
public class CacheConfig { }

@Service
public class ProductService {

    @Cacheable(value = "products", key = "#id")
    public Product findById(Long id) { }

    @CachePut(value = "products", key = "#product.id")
    public Product update(Product product) { }

    @CacheEvict(value = "products", key = "#id")
    public void delete(Long id) { }

    @CacheEvict(value = "products", allEntries = true)
    public void clearCache() { }
}

Design Decisions

Q29: When to use Spring WebFlux?

Use WebFlux when: - High concurrency with many concurrent connections - Streaming data - Microservices calling multiple downstream services - Non-blocking I/O operations

Stick with MVC when: - JDBC/JPA (blocking by nature) - Simple CRUD applications - Team unfamiliar with reactive programming


Q30: Microservices Patterns with Spring?

// Service Discovery (Eureka)
@EnableDiscoveryClient

// Load Balancing
@LoadBalanced
@Bean
public RestTemplate restTemplate() { }

// Circuit Breaker (Resilience4j)
@CircuitBreaker(name = "payment", fallbackMethod = "paymentFallback")
public Payment processPayment(Order order) { }

// Distributed Tracing
// spring-cloud-starter-sleuth + zipkin

// Config Server
// spring-cloud-config-server

Quick Reference Table

Annotation Purpose
@Component Generic Spring bean
@Service Business logic layer
@Repository Data access layer
@Controller Web MVC controller
@RestController REST API controller
@Configuration Configuration class
@Bean Method-level bean definition
@Autowired Dependency injection
@Value Property injection
@Transactional Transaction boundary
@Cacheable Cache method result
@Async Async execution
@Scheduled Scheduled task
@PreAuthorize Method-level security
@Valid Bean validation

  • *