Friday, 27 June 2025

Java 21 features in Collections

 Java 21 introduces several new features and enhancements in Collections, especially with the ongoing development of the Stream API, immutable collections, and sequenced collections.

Here are the important new features in Collections in Java 21:


✅ 1. Sequenced Collections (JEP 431) — 🔥 New!

📌 What?

Introduces a new SequencedCollection interface that adds first/last element access and reversible traversal to collections.

📦 New Interfaces:

public interface SequencedCollection<E> extends Collection<E> { E getFirst(); E getLast(); void addFirst(E e); void addLast(E e); E removeFirst(); E removeLast(); SequencedCollection<E> reversed(); }

✅ Applies to:

  • ArrayDeque

  • LinkedList

  • TreeSet

  • ArrayList (via SequencedCollection interface)

  • HashSet

  • Map types → via SequencedMap

🔍 Example:

List<String> list = new ArrayList<>(List.of("A", "B", "C")); SequencedCollection<String> seq = (SequencedCollection<String>) list; System.out.println(seq.getFirst()); // A System.out.println(seq.getLast()); // C seq.addFirst("X"); seq.addLast("Y"); System.out.println(seq); // [X, A, B, C, Y] System.out.println(seq.reversed()); // [Y, C, B, A, X]

✅ 2. Unmodifiable Collections Enhancements

Previously, Map.of(...), List.of(...), etc. returned immutable collections. With SequencedCollection, now you can traverse them in order and reverse:

SequencedCollection<Integer> nums = List.of(1, 2, 3); System.out.println(nums.reversed()); // [3, 2, 1]

✅ 3. Immutable SequencedMap and SequencedSet

You can now work with insertion-ordered maps and sets:

SequencedMap<String, Integer> map = Map.of("a", 1, "b", 2, "c", 3); System.out.println(map.firstEntry()); // a=1 System.out.println(map.lastEntry()); // c=3 System.out.println(map.reversed()); // {c=3, b=2, a=1}

✅ 4. Pattern Matching + Collections (Java 21 + Preview)

Pattern matching can now destructure collections (as a preview feature):


Object obj = List.of("hello", "world"); if (obj instanceof List<String> list && list.size() == 2) { System.out.println("First: " + list.getFirst()); }

✅ 5. Stream Improvements

Stream.mapMulti() (Added in Java 16, still crucial)

Gives better performance and flexibility than flatMap.


List<Integer> input = List.of(1, 2, 3); List<Integer> doubled = input.stream() .<Integer>mapMulti((e, consumer) -> { consumer.accept(e); consumer.accept(e * 2); }) .collect(Collectors.toList()); // Output: [1, 2, 2, 4, 3, 6]

🔮 Optional Preview Features in Java 21 (might impact future collection usage)

  • Record Patterns

  • String Templates

  • Scoped Values (for threads)


✅ Summary Table

FeatureDescriptionExample Class
SequencedCollectionNew interface for order-aware collectionsArrayList, LinkedList
reversed()Reverses any sequenced collection/mapList, Set, Map
addFirst(), getLast()First/last item accessSequencedCollection
SequencedMapOrdered maps with head/tail accessLinkedHashMap, TreeMap
Pattern Matching (preview)Destructure lists/mapsinstanceof usage

Wednesday, 25 June 2025

Design patterns in java

Design patterns are standard solutions to common software design problems.
They are like templates you can use in different situations to write flexible, reusable, and maintainable code.

Java design patterns are categorized into three main types:

📌 Summary Diagram

Design Patterns

├── Creational (object creation mechanisms)

│   ├── Singleton

│   ├── Factory Method

│   ├── Abstract Factory

│   ├── Builder

│   └── Prototype

├── Structural (Class and object composition)

│   ├── Adapter

│   ├── Bridge

│   ├── Composite

│   ├── Decorator

│   ├── Facade

│   ├── Flyweight

│   └── Proxy

└── Behavioral (Communication between objects)

    ├── Chain of Responsibility

    ├── Command

    ├── Interpreter

    ├── Iterator

    ├── Mediator

    ├── Memento

    ├── Observer

    ├── State

    ├── Strategy

    ├── Template Method

    └── Visitor

 ✅ 1. Creational Design Patterns

These patterns deal with object creation mechanisms, trying to create objects in a manner suitable to the situation.


🔹 a. Singleton Pattern

The Singleton Pattern is a creational design pattern that ensures a class has only one instance throughout the application lifecycle and provides a global point of access to that instance. This pattern is often used for managing shared resources like configuration objects, logging, or database connections.

Use When: You need to control access to shared resources (e.g., configuration, logging).

Example 1: Synchronized Method (Simple but less efficient)
public class Singleton { private static Singleton instance; //staic keyword private Singleton() {} // private constructor public static synchronized Singleton getInstance() { //synchronized keyword if (instance == null) { instance = new Singleton(); } return instance; } }
Pros: Thread-safe Cons: Synchronization overhead every time getInstance() is called, even after initialization. ----------------- 2. Double-Checked Locking (Efficient and Thread-safe)
public class Singleton { private static volatile Singleton instance; //staic,volatile keywords
private Singleton() {} // private constructor public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { //synchronized keyword if (instance == null) { instance = new Singleton(); } } } return instance; } } Pros: Thread-safe, efficient Cons: Slightly more complex volatile ensures visibility of changes across threads. 3. Bill Pugh Singleton (Recommended for most use cases)
public class Singleton { private Singleton() {} // private constructor private static class SingletonHelper { //staic keyword private static final Singleton INSTANCE = new Singleton(); //staic,final keywords } public static Singleton getInstance() { return SingletonHelper.INSTANCE; } } Pros: Thread-safe, lazy-loaded, no synchronization overhead Cons: Slightly less intuitive


🔹 b. Factory Pattern

Definition: The Factory Pattern is a creational design pattern that provides a way to create objects without exposing the creation logic to the client. Instead of using new, you call a factory method to get an object.

Factory Design Pattern is a creational pattern that provides an interface or method to create objects in a superclass, but allows subclasses or the factory method to decide which class to instantiate.

Use When: You have a superclass with multiple subclasses and need to return one of the subclasses based on input.

interface Shape {

void draw();

}


// Concrete implementations

class Circle implements Shape {

public void draw() {

System.out.println("Drawing Circle");

}

}


class Square implements Shape {

public void draw() {

System.out.println("Drawing Square");

}

}


// Factory class

class ShapeFactory {

public static Shape getShape(String type) {

if ("CIRCLE".equalsIgnoreCase(type)) {

return new Circle();

} else if ("SQUARE".equalsIgnoreCase(type)) {

return new Square();

}

throw new IllegalArgumentException("Unsupported Shape: " + type);

}

}


// Usage

public class FactoryPattern {

public static void main(String[] args) {

Shape shape = ShapeFactory.getShape("circle");

shape.draw(); // Output: Drawing Circle

Shape shape1 = ShapeFactory.getShape("Square");

shape1.draw(); // Output: Drawing Square

}

}

🔹 c. Abstract Factory Pattern

Definition: Factory of factories. It provides an interface for creating families of related objects without specifying concrete classes.

Use When: You want to create related objects without knowing their concrete classes.

// Product interface

interface Shape {

void draw();

}


// Concrete products

class Circle implements Shape {

public void draw() {

System.out.println("Drawing Circle");

}

}


class Square implements Shape {

public void draw() {

System.out.println("Drawing Square");

}

}


// Abstract Factory

interface AbstractFactory {

Shape createShape();

}


// Concrete Factory 1

class CircleFactory implements AbstractFactory {

public Shape createShape() {

return new Circle();

}

}


// Concrete Factory 2

class SquareFactory implements AbstractFactory {

public Shape createShape() {

return new Square();

}

}


// Factory Producer (optional, selects the correct factory)

class FactoryPattern {

public static AbstractFactory getFactory(String shapeType) {

if ("CIRCLE".equalsIgnoreCase(shapeType)) {

return new CircleFactory();

} else if ("SQUARE".equalsIgnoreCase(shapeType)) {

return new SquareFactory();

}

throw new IllegalArgumentException("Unsupported Shape Factory: " + shapeType);

}

}


// Client

public class AbstractFactoryPattern {

public static void main(String[] args) {

AbstractFactory circleFactory = FactoryPattern.getFactory("CIRCLE");

Shape circle = circleFactory.createShape();

circle.draw(); // Output: Drawing Circle


AbstractFactory squareFactory = FactoryPattern.getFactory("SQUARE");

Shape square = squareFactory.createShape();

square.draw(); // Output: Drawing Square

}

}


🔹 d. Builder Pattern

Definition: The Builder Pattern is a creational design pattern used to construct complex objects step by step, especially when an object has many optional parameters. It helps create immutable objects with better readability and flexibility.

Use When: You want to construct complex objects in a readable and controlled manner.

class Product { private String partA; private String partB; public static class Builder { private final Product product = new Product(); public Builder setPartA(String partA) { product.partA = partA; return this; } public Builder setPartB(String partB) { product.partB = partB; return this; } public Product build() { return product; } } } // Usage Product p = new Product.Builder() .setPartA("CPU") .setPartB("RAM") .build();

🔹 e. Prototype Pattern

Definition: The Prototype Pattern is a creational design pattern that lets you create a copy (clone) of an existing object, instead of creating a new one from scratch. 

Use When: Object creation is costly.

class Prototype implements Cloneable { int id; public Prototype(int id) { this.id = id; } public Prototype clone() throws CloneNotSupportedException { return (Prototype) super.clone(); } } // Usage Prototype p1 = new Prototype(10); Prototype p2 = p1.clone();

✅ 2. Structural Design Patterns

These patterns deal with object composition, helping ensure classes work together properly.


🔹 a. Adapter Pattern

Definition: The Adapter Pattern is a structural design pattern that allows incompatible interfaces to work together. It acts as a bridge between two different interfaces by converting one into another.

Use When: You want to use an existing class but its interface does not match your requirements.

java
interface MediaPlayer { void play(String audioType, String fileName); } class MP3Player implements MediaPlayer { public void play(String audioType, String fileName) { if (audioType.equalsIgnoreCase("mp3")) System.out.println("Playing MP3: " + fileName); } } class VLCPlayer { void playVLC(String fileName) { System.out.println("Playing VLC: " + fileName); } } class MediaAdapter implements MediaPlayer { VLCPlayer vlcPlayer = new VLCPlayer(); public void play(String audioType, String fileName) { if (audioType.equalsIgnoreCase("vlc")) vlcPlayer.playVLC(fileName); } } // Usage MediaPlayer player = new MediaAdapter(); player.play("vlc", "movie.vlc");

🔹 b. Decorator Pattern

Definition: The Decorator Pattern is a structural design pattern that allows you to add new behavior or functionality to an object dynamically, without changing its structure or code.

Use When: You want to add new functionality without altering existing code.

Follows Open/Closed Principle: Open for extension, closed for modification.

java

interface Car { void assemble(); } class BasicCar implements Car { public void assemble() { System.out.print("Basic Car"); } } class SportsCar implements Car { private final Car car; public SportsCar(Car car) { this.car = car; } public void assemble() { car.assemble(); System.out.print(" + Sports Features"); } } // Usage Car car = new SportsCar(new BasicCar()); car.assemble(); // Output: Basic Car + Sports Features

🔹 c. Facade Pattern

Definition: The Facade Pattern is a structural design pattern that provides a simplified interface to a complex system of classes, libraries, or frameworks. It hides the complexities and exposes only what is necessary to the client.

java

class CPU { void start() { System.out.println("CPU Started"); } } class Memory { void load() { System.out.println("Memory Loaded"); } } class ComputerFacade { private final CPU cpu = new CPU(); private final Memory memory = new Memory(); public void startComputer() { cpu.start(); memory.load(); } } // Usage ComputerFacade computer = new ComputerFacade(); computer.startComputer();

✅ 3. Behavioral Design Patterns

These focus on communication between objects.

In the Java Collection Framework (JCF), several Behavioral Design Patterns are internally used. Here's a breakdown of which ones apply and how: Command Pattern, Iterator Pattern, Observer Pattern, Strategy Pattern

PatternUsed in Java CollectionsExample
Iterator✅ Yeslist.iterator()
Observer✅ Yes (legacy)Observable and Observer
Strategy✅ YesCollections.sort(list, comparator)
Command✅ IndirectlyRunnable, ExecutorService.submit(command)
Others❌ NoNot directly applied in collections

🔹 a. Command Pattern

Definition: Encapsulate a request as an object.

The Command Pattern is a behavioral design pattern that turns a request into an object, allowing you to parameterize methods with different requests, queue them, or log them. It also supports undo/redo operations.

Simple example 1:

Runnable command = () -> System.out.println("Task executed");

new Thread(command).start();

Java uses this pattern indirectly in many places, especially where:

Framework / FeatureUsage of Command Pattern
Runnable, CallableEach task is a command encapsulating business logic.
ExecutorServiceExecutes submitted commands (Runnable/Callable).
Swing / AWT Event ModelGUI events (buttons, menu items) encapsulate commands.
ActionListenerMethod calls are treated as command executions.
ScheduledExecutorServiceQueues and executes delayed commands.      
Purpose in Java: Encapsulate task logic independently of how it is executed. Allow asynchronous execution via thread pools (ExecutorService). Enable command queuing, logging, or undo operations in custom implementations.

java 
interface Command { void execute(); } class Light { void on() { System.out.println("Light ON"); } void off() { System.out.println("Light OFF"); } } class LightOnCommand implements Command { private final Light light; LightOnCommand(Light light) { this.light = light; } public void execute() { light.on(); } } class RemoteControl { Command command; void setCommand(Command command) { this.command = command; } void pressButton() { command.execute(); } } // Usage Light light = new Light(); Command command = new LightOnCommand(light); RemoteControl remote = new RemoteControl(); remote.setCommand(command); remote.pressButton(); // Output: Light ON


b. Iterator Pattern — ✔️ Used

Where?

Iterator interface in all Java collections (e.g., List, Set, Map).


Purpose:

To traverse collections without exposing the internal structure.


Example:

java

List<String> names = Arrays.asList("A", "B", "C");

Iterator<String> it = names.iterator();

while (it.hasNext()) {

    System.out.println(it.next());

}

🔹 b. Observer Pattern

Definition: The Observer Pattern is a behavioral design pattern where an object (called Subject) maintains a list of observers and notifies them automatically of any state changes. One-to-many dependency between objects. If one changes, all dependents are notified.

Use When: Implement event handling systems.

java
interface Observer { void update(String msg); } class Subscriber implements Observer { private final String name; Subscriber(String name) { this.name = name; } public void update(String msg) { System.out.println(name + " received: " + msg); } } class Publisher { List<Observer> observers = new ArrayList<>(); void subscribe(Observer o) { observers.add(o); } void notifyAllObservers(String msg) { for (Observer o : observers) o.update(msg); } } // Usage Publisher pub = new Publisher(); pub.subscribe(new Subscriber("A")); pub.subscribe(new Subscriber("B")); pub.notifyAllObservers("Hello");

🔹 c. Strategy Pattern

Definition: The Strategy Pattern is a behavioral design pattern that allows you to define a family of algorithms, put each in a separate class, and switch between them at runtime without changing the client code.

Use When: You want to change behavior dynamically.
Sample Example1:

java

List<String> list = Arrays.asList("Z", "A", "M");

Collections.sort(list, (a, b) -> a.compareTo(b)); // Strategy pattern

Where?

Sorting strategies in Collections.sort() using Comparator


Purpose:

Allows changing the sorting algorithm or logic at runtime.


java
interface PaymentStrategy { void pay(int amount); } class CreditCardPayment implements PaymentStrategy { public void pay(int amount) { System.out.println("Paid with credit card: " + amount); } } class PaypalPayment implements PaymentStrategy { public void pay(int amount) { System.out.println("Paid with PayPal: " + amount); } } class Context { private PaymentStrategy strategy; Context(PaymentStrategy strategy) { this.strategy = strategy; } void pay(int amount) { strategy.pay(amount); } } // Usage Context context = new Context(new CreditCardPayment()); context.pay(500);

 4. Microservices-Specific Design Patterns

a)API Gateway Pattern

Used in: Centralizing requests in microservices architecture (Spring Cloud Gateway)
@Configuration
 p public class ApiGatewayConfig {
    @Bean
    public RouteLocator routes(RouteLocatorBuilder builder) {
        return builder.routes()
            .route("user-service", r -> r.path("/users/**").uri("lb://USER-SERVICE"))
            .route("order-service", r -> r.path("/orders/**").uri("lb://ORDER-SERVICE"))
            .build();
    }
 } @Configuration
 p public class ApiGatewayConfig {
    @Bean
    public RouteLocator routes(RouteLocatorBuilder builder) {
        return builder.routes()
            .route("user-service", r -> r.path("/users/**").uri("lb://USER-SERVICE"))
            .route("order-service", r -> r.path("/orders/**").uri("lb://ORDER-SERVICE"))
            .build();
    }
 }
   b)Circuit Breaker Pattern
Used in: Fault tolerance (Resilience4j, Hystrix)
@RestController
 p public class PaymentController {
    @Autowired
    private PaymentService paymentService;

    @GetMapping("/pay")
    @CircuitBreaker(name = "paymentService", fallbackMethod = "fallbackPayment")
    public String processPayment() {
        return paymentService.pay();
    }

    public String fallbackPayment(Exception e) {
        return "Payment Service is currently unavailable.";
    }
   }

C  Conclusion

In   my Spring Boot project, these design patterns help improve:

  • Scalability (e.g., Microservices patterns like API Gateway, Circuit Breaker)
  • Code reusability (e.g., Template Method, Strategy Pattern)
  • Maintainability (e.g., Singleton, Factory, Proxy)
  • Extensibility (e.g., Observer, Decorator)

✅ Summary Table

PatternCategoryPurpose
SingletonCreationalOne instance, global access
FactoryCreationalCreates object based on input
Abstract FactoryCreationalCreates related families of objects
BuilderCreationalStep-by-step object construction
PrototypeCreationalClone existing object
AdapterStructuralConverts one interface to another
DecoratorStructuralAdds behavior dynamically
FacadeStructuralSimplifies subsystem access
ObserverBehavioralPublish-subscribe model
StrategyBehavioralChoose algorithm at runtime
CommandBehavioralEncapsulate actions as objects

Internal flow of spring boot/spring/spring mvc

The internal flow of Spring Boot refers to what happens behind the scenes when you run a Spring Boot application — from startup to handling requests. 


🔁 1. Application Startup (main() method)

@SpringBootApplication

public class MyApp { public static void main(String[] args) { SpringApplication.run(MyApp.class, args); } }

When you run a Spring Boot application using the entry point(SpringApplication.run(...)) then bootstraps the entire Spring Boot application

  • And creates a SpringApplication object.

  • And sets up:

    • Environment (like application.properties)

    • ApplicationContext (Spring Container)

    • Auto-configuration

    • Logging system

    • Banner display

    • Listeners and initializers


🔧 2. Component Scan & Bean Creation

Triggered by:

java
@SpringBootApplication // = @Configuration + @ComponentScan + @EnableAutoConfiguration

Internals:

  • And ComponentScan internally scans all classes under the base package and sub-packages.

  • Registers beans for:

    • @Component, @Service, @Repository, @Controller, @RestController

  • Spring’s BeanFactory or ApplicationContext creates and manages the lifecycle of these beans.

  • Dependency injection using @Autowired, @Value, @Qualifier, etc.


⚙️ 3. Auto Configuration

Provided by:

java
@EnableAutoConfiguration

Internals:

  • Uses spring.factories to load classes annotated with @Configuration.

  • Auto-configures beans (like DataSource, Kafka, MVC, etc.) based on classpath and properties.

  • Uses conditional annotations like:

    • @ConditionalOnClass

    • @ConditionalOnMissingBean

    • @ConditionalOnProperty


🛠 4. Initialization of Embedded Server

Example:

  • Tomcat (default), Jetty, or Undertow

Internals:

  • Spring Boot auto-configures and starts the embedded server.

  • DispatcherServlet is initialized and mapped to handle all requests (/).

  • Servlet context is set up.


🌐 5. Request Handling (Web Layer)

Steps:

  1. HTTP request hits the embedded server (Tomcat).

  2. Routed to the DispatcherServlet.

  3. DispatcherServlet uses HandlerMapping to find the correct controller method.

  4. Executes:

    • HandlerInterceptors

    • Controller method (e.g., @GetMapping, @PostMapping)

  5. Returns the result (ResponseEntity, JSON, View).

  6. DispatcherServlet sends response back to the client.


📦 6. Persistence Layer (If Configured)

  • Auto-configures:

    • DataSource (JDBC or JPA)

    • Hibernate EntityManager

    • Repositories via @Repository and @EnableJpaRepositories

  • Transaction management via @Transactional


📊 7. Actuator & Monitoring (Optional)

  • Spring Boot Actuator auto-configures endpoints for:

    • /actuator/health

    • /actuator/info

    • /actuator/metrics

  • Useful for health checks and integration with Prometheus/Grafana


🛑 8. Shutdown Flow

  • Triggers graceful shutdown:

    • Calls SmartLifecycle.stop()

    • Closes ApplicationContext

    • Releases resources (e.g., DB connections, Kafka consumers)

  • Beans with @PreDestroy or implementing DisposableBean are cleaned up.


⚙️ Internal Components Summary

ComponentRole
SpringApplicationBootstraps and configures the application
ApplicationContextManages beans and dependency injection
DispatcherServletFront controller for web requests
BeanPostProcessorAllows custom modification of beans
@ConfigurationDeclares Spring configurations
@EnableAutoConfigurationEnables Spring Boot’s intelligent auto setup
CommandLineRunner / ApplicationRunnerExecutes code after startup      

🔍 Spring Boot Internal Flow

✅ Visual Diagram + Call Stack Trace


📌 A. Visual Architecture Diagram of SpringApplication.run(...)


+------------------------------------------------------+ | Your Application Class | | @SpringBootApplication | | public class MyApp { | | public static void main(String[] args) { | | SpringApplication.run(MyApp.class, args); | | } | | } | +---------------------------|--------------------------+ | v +----------------------------[SpringApplication.run()]-----------------------------+ | | | 1. Create SpringApplication instance | | - Set application type (Servlet, Reactive, None) | | - Load initializers and listeners (from spring.factories) | | | | 2. Prepare Environment | | - Load `application.properties`, profiles, command-line args, env vars | | - Configure ConfigurableEnvironment | | | | 3. Create ApplicationContext (IoC container) | | - e.g., AnnotationConfigServletWebServerApplicationContext | | | | 4. Refresh ApplicationContext (Spring Core) | | - Call AbstractApplicationContext.refresh() | | a. Prepare BeanFactory | | b. Load Bean Definitions (via classpath scanning) | | c. Register BeanPostProcessors | | d. Instantiate Singleton Beans | | e. Inject Dependencies (`@Autowired`, etc.) | | f. Apply Lifecycle Callbacks (`@PostConstruct`, AOP proxies, etc.) | | | | 5. Run ApplicationRunner / CommandLineRunner | | | | 6. Publish ApplicationReadyEvent | +----------------------------------------------------------------------------------+ | v 🚀 Application is Ready to Handle Requests

📌 B. Internal Call Stack Trace

(Important Classes and Methods Behind the Scenes)


java
// Entry point SpringApplication.run(MyApp.class, args) // → Step 1: Constructor new SpringApplication(MyApp.class) └── setInitializers() └── setListeners() └── deduceApplicationType() // → Step 2: Run method SpringApplication.run() └── prepareEnvironment() └── configurePropertySources() └── bindEnvironmentProperties() └── printBanner() └── createApplicationContext() └── AnnotationConfigServletWebServerApplicationContext └── prepareContext() └── applyInitializers() └── listeners.contextPrepared() └── refreshContext() → context.refresh() // → Step 3: Spring Core Container (IoC) AbstractApplicationContext.refresh() └── prepareBeanFactory() └── invokeBeanFactoryPostProcessors() └── registerBeanPostProcessors() └── initMessageSource() └── initApplicationEventMulticaster() └── onRefresh() // For web apps: create embedded Tomcat, setup dispatcher └── registerListeners() └── finishBeanFactoryInitialization() └── create all singleton beans └── apply dependency injection └── finishRefresh() // → Step 4: Call ApplicationRunners └── callRunners(context, args) └── invoke all ApplicationRunner & CommandLineRunner beans // → Step 5: Events Published └── ApplicationStartedEvent └── ApplicationReadyEvent

📦 Summary Diagram:

SpringApplication.run() | └── Create SpringApplication instance | └── Prepare Environment | └── Create ApplicationContext (Spring Container) | └── refresh() ├── Load bean definitions ├── Instantiate beans ├── Inject dependencies └── Apply lifecycle methods | └── Application is ready

✅ Key Classes Involved:

ComponentResponsibility
SpringApplicationEntry point for bootstrapping the app
ConfigurableApplicationContextSpring’s container holding all beans
ApplicationContextInitializerModify context before refresh
BeanFactoryPostProcessorModify BeanFactory before beans instantiated
BeanPostProcessorModify beans after instantiation
AnnotationConfigServletWeb...CtxIoC + embedded web server (Tomcat)
@SpringBootApplicationCombo of @Configuration, @ComponentScan, @EnableAutoConfiguration
ApplicationRunner, CommandLineRunnerCode to run just before app is ready

📌 Optional: View Actual SpringApplication.run() Flow in Debug Mode

Set a breakpoint in your IDE:

java
SpringApplication.run(MyApp.class, args);

And then step into to trace each class mentioned above.

SpringApplication class in Spring Boot

SpringApplication is a class in Spring Boot that is responsible for bootstrapping and launching a Spring application from the main() method. It sets up the Spring ApplicationContext, performs auto-configuration, and starts the embedded server (like Tomcat).


📌 Simple Definition:

SpringApplication is the entry point used to start a Spring Boot application.


🧱 Syntax:

java
SpringApplication.run(ApplicationClass.class, args);

🔧 Example:

java
@SpringBootApplication public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } }

🔍 What It Does Internally:

  1. Creates an ApplicationContext

  2. Loads beans and applies auto-configuration

  3. Sets up logging, environment, and banner

  4. Starts embedded web server (Tomcat/Jetty/Undertow)

  5. Runs any CommandLineRunner or ApplicationRunner beans


🔩 Advanced Usage:

java
SpringApplication app = new SpringApplication(MyApplication.class); app.setBannerMode(Banner.Mode.OFF); app.run(args);

📚 Key Features:

  • Auto-configuration

  • Environment loading (application.properties/yaml)

  • Command line argument parsing

  • Banner control

  • Listener and event publishing support

---------------------------

✅ 2. Spring Framework Internal Flow

🌱 Spring Core Container Flow

  • IoC Container (Inversion of Control):

    • Reads configuration (@Configuration, @Component)

    • Instantiates beans

    • Resolves dependencies via:

      • @Autowired, @Qualifier, @Primary, XML, etc.

🔄 Bean Lifecycle:

  1. Instantiation

  2. Populate properties (@Autowired, setters)

  3. BeanNameAware, BeanFactoryAware callbacks

  4. InitializingBean.afterPropertiesSet() or @PostConstruct

  5. Bean is ready to use

  6. On shutdown: @PreDestroy or DisposableBean.destroy()


✅ 3. Spring MVC Internal Flow

🌐 HTTP Request Flow (Spring Web MVC DispatcherServlet)

text
Client -> Embedded Tomcat -> DispatcherServlet -> HandlerMapping -> Controller -> Service -> Repository -> DB <- ResponseBody/ModelAndView <- ViewResolver <- DispatcherServlet <- Client

🔁 Step-by-step Request Flow:


🔹 1. Client Sends HTTP Request

Example: GET /users/123


🔹 2. DispatcherServlet (Front Controller)

  • Configured by Spring Boot auto-config.

  • Intercepts all incoming requests (/ mapping).

  • Delegates request to appropriate components.


🔹 3. HandlerMapping

  • Finds appropriate @Controller class & method based on URL and HTTP method.

  • Ex: @GetMapping("/users/{id}")


🔹 4. HandlerAdapter

  • Executes the controller method.


🔹 5. Controller Method

java
@GetMapping("/users/{id}") public ResponseEntity<User> getUser(@PathVariable int id) { return ResponseEntity.ok(userService.findById(id)); }
  • Calls the Service layer.

  • Business logic executes.


🔹 6. Service Layer

  • Contains business logic

  • Calls the Repository (DAO)


🔹 7. Repository Layer

  • Interacts with the DB using JPA/Hibernate.

java
@Repository public interface UserRepository extends JpaRepository<User, Integer> {}

🔹 8. Return Response

  • Controller returns ResponseEntity or object.

  • If annotated with @RestController or @ResponseBody, data is serialized (JSON/XML) by HttpMessageConverters (like Jackson).


🔹 9. ViewResolver (If using Thymeleaf/JSP)

  • If returning a view name, ViewResolver resolves it to an actual .html or .jsp.


🔹 10. Response Sent to Client


✅ Internal Objects in Spring MVC

ComponentPurpose
DispatcherServletCentral controller of Spring MVC
HandlerMappingFinds which controller to call
HandlerAdapterCalls the actual controller method
HttpMessageConverterConverts object to JSON/XML
ViewResolverResolves view names to templates
ModelAndViewHolds model + view data
WebDataBinderBinds request params to Java objects

🔚 Summary Diagram

SpringApplication.run() ↓ Creates ApplicationContextScans Beans (@Component, etc.) ↓ Initializes DispatcherServletStarts Embedded Server (Tomcat) ↓ Client HTTP RequestDispatcherServletHandlerMappingControllerServiceRepositoryDBController returns Response/ModelAndViewHttpMessageConverter/ViewResolverResponse back to Client

🔍 Detailed Breakdown:

✅ 1. SpringApplication.run(...) This is the entry point to boot your Spring Boot application. It performs: Environment preparation ApplicationContext creation Auto-configuration Running ApplicationRunner or CommandLineRunner beans Internally: java public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args)
✅ 2. Creates ApplicationContext Based on the application type (web or non-web), it creates: AnnotationConfigServletWebServerApplicationContext (for Spring MVC) or another variant like ReactiveWebServerApplicationContext (for WebFlux) This is the Spring container that manages all beans and lifecycle. ✅ 3. Scans Beans (@Component, @Service, @Controller, etc.) Spring scans packages based on: @SpringBootApplication → combines @ComponentScan Beans annotated with: @Component, @Service, @Repository, @Controller, @RestController These are registered in the ApplicationContext. ✅ 4. Initializes DispatcherServlet The DispatcherServlet is the Front Controller in Spring MVC. It is automatically registered as a bean and mapped to /. It handles all incoming HTTP requests. ✅ 5. Starts Embedded Server (Tomcat/Jetty/Undertow) Spring Boot uses embedded servers (default is Tomcat). The server is started programmatically, no need for web.xml. Example log: scss Tomcat started on port(s): 8080 (http)
✅ 6. Client HTTP Request A user (browser/API client) makes an HTTP request: bash GET http://localhost:8080/users ✅ 7. DispatcherServlet DispatcherServlet intercepts the request. It is configured via WebMvcAutoConfiguration. It coordinates the request-handling workflow. ✅ 8. HandlerMapping → Controller DispatcherServlet asks HandlerMapping for the correct controller. Finds a @RequestMapping, @GetMapping, etc. Then, calls the method in the controller class: java @RestController public class UserController { @GetMapping("/users") public List<User> getUsers() { ... } } ✅ 9. Service → Repository → DB The controller delegates logic to the @Service layer. The service calls the @Repository, which interacts with the database: java @Service public class UserService { @Autowired private UserRepository repo; public List<User> getAllUsers() { return repo.findAll(); } } ✅ 10. Controller returns Response or ModelAndView The controller returns: ResponseEntity<?> for REST Or ModelAndView for traditional MVC Spring uses this return type to decide how to process the response. ✅ 11. HttpMessageConverter / ViewResolver If REST: Uses HttpMessageConverter (e.g., Jackson) to convert Java objects → JSON/XML If MVC: Uses ViewResolver to resolve .jsp or .html views ✅ 12. Response back to Client The generated response (JSON, HTML, etc.) is sent back via HTTP to the client: css HTTP 200 OK Content-Type: application/json Body: [{"id":1,"name":"John"}, ...] ✅ Summary Flow Diagram text SpringApplication.run() ↓ ApplicationContext created ↓ Beans scanned and registered ↓ Embedded server (Tomcat) started ↓ ↓ Client makes request DispatcherServlet receives it ↓ HandlerMapping → Controller method ↓ Service → Repository → DB ↓ Controller returns response ↓ HttpMessageConverter or ViewResolver ↓ HTTP Response to client