Skip to main content

πŸ§™ How Does Spring Boot Really Find Stuff?! (And How @SpringBootApplication + META-INF/spring.factories Do Their Secret Scan Magic)

 

😡‍πŸ’« When I started working in Spring Boot, I had a silly doubt… but it unlocked a serious concept.

I knew that @SpringBootApplication does a lot — it’s the entry point of every Spring Boot app.

So far, I only knew the basics:


@SpringBootApplication = @Configuration + @EnableAutoConfiguration + @ComponentScan

But one day I asked myself:

πŸ’­ “How does Spring Boot load classes from external libraries like spring-security, spring-web, or even a custom JAR I wrote and added in dependencies?
I never wrote any @ComponentScan for them… so how are their beans magically appearing inside my Spring Context?”

Yeah yeah… people say “Auto-configuration” or “Classpath scanning.” But how? Let’s deep dive πŸ”


πŸšͺ Let’s First Talk About @ComponentScan

By default, this only scans packages below the class where @SpringBootApplication is placed.

So if your MainApp.java is in com.anand.app, it will scan:

com.anand.app.*

But will it scan classes inside:

org.springframework.security.config.annotation.*

πŸ€” Nope. Not unless Spring does something behind the scenes.


🧳 Then How Are External JARs Loaded?

Let’s take Spring Web as an example.

You just add this:


<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>

πŸ’₯ Boom! You get a running server, a DispatcherServlet, Jackson for JSON, exception resolvers… like magic.

But where’s the magic wand?

That wand is called:


META-INF/spring.factories

πŸ—‚️ What’s This spring.factories?

Inside each Spring Boot starter JAR, you’ll find:


META-INF/spring.factories

This file tells Spring Boot:

“Hey, I have some config classes to load. Even if the user didn’t scan me manually.”

Example from spring-boot-autoconfigure:


org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\ org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\ ...more...

This is how Spring Boot “auto-magically” adds beans — they’re listed here and picked up by @EnableAutoConfiguration.


πŸ§ͺ So What Does @EnableAutoConfiguration Actually Do?

It does the heavy lifting. Here’s how:

  1. Scans the classpath for META-INF/spring.factories

  2. Loads all classes listed under EnableAutoConfiguration

  3. Instantiates them as configuration classes

  4. Each of them adds beans conditionally using annotations like:


@Bean @ConditionalOnClass(ObjectMapper.class)

So:

  • If Jackson is present → JSON config is loaded.

  • If not → config is skipped.

✨ It’s intelligent — it won’t load everything blindly.


πŸ”„ Spring 2.7+ — What Changed?

Starting with Spring Boot 2.7+, this mechanism evolved for performance and modularity.

Now many starters use:


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

This is part of the newer @AutoConfiguration mechanism using AutoConfigurationImportSelector.

But the idea is the same — it loads stuff without requiring you to @ComponentScan them.


πŸ§ͺ Real Example — How DispatcherServlet Comes In

Ever used a simple @RestController and hit it in browser?

You never configured a DispatcherServlet, right?

But this class is magically loaded from:


org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration

Which comes from:

spring.factories > EnableAutoConfiguration

Inside, it does:


@Bean public DispatcherServlet dispatcherServlet() { return new DispatcherServlet(); }

Spring Boot sees this during auto-config loading and registers it as a servlet.

πŸŽ‰ Boom. Your REST controller works.


🀹 Custom JARs Work the Same Way!

Want to create your own reusable Spring Boot library?

✅ Add your @Configuration class
✅ Put it in:


src/main/resources/META-INF/spring.factories

Like this:


org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.mycompany.autoconfig.MyCustomConfig

Now any project that adds your JAR will have this config loaded.


πŸ’₯ That’s Why Just Adding a Starter Works

Whether it’s:

  • spring-boot-starter-data-jpa

  • spring-boot-starter-security

  • resilience4j-spring-boot2

…they all use either:

  • spring.factories (older)

  • or AutoConfiguration.imports (newer)

No manual scanning. No XML. Just plugin and go.


πŸ”š Wrapping Up

This small doubt I had while exploring Spring Boot opened up a whole world of internal magic — how Spring loads, scans, wires, and bootstraps everything without you even noticing.

Next time you wonder,

“How did that bean get in here?”

Remember: Spring invited it through a secret VIP list 🎟️ in META-INF.


πŸ’¬ Did this help you clear some Spring mystery?

Tell me if you ever faced confusion like this — I’ll try to explain it with more examples .


Stay curious, stay caffeinated ☕ and keep debugging.

— Anand πŸ§‘‍πŸ’»

Comments

Popular posts from this blog

🐱 Tomcat vs ⚡ Netty – Which One Should You Use?

🐱 Tomcat vs ⚡ Netty – Which One Should You Use? So recently I got curious about this too πŸ€”. Everywhere in Spring Boot tutorials we see Tomcat . Then suddenly while exploring Spring WebFlux , the name Netty pops up. And I was like – “Wait, who’s this Netty guy trying to replace Tomcat?” πŸ˜… Let’s break it down with real-time examples , icons , and fun comparisons . 🐱 Tomcat – The Traditional Web Server Type: Servlet Container (blocking I/O) World: Used with Spring MVC Style: Thread-per-request model πŸ‘©‍πŸ’» Pros: Stable, widely used, battle-tested Cons: Struggles with huge concurrent connections πŸ‘‰ Example in real life: Tomcat is like a restaurant with fixed waiters 🍴. - Each customer = one thread/waiter - If too many customers come in at once → waiters run out → customers wait outside πŸšͺ ⚡ Netty – The Reactive Rockstar Type: Asynchronous Event-Driven Network Framework World: Default for Spring WebFlux Style: Event-lo...

🎭 Spring’s Secret: Why @Transactional & Friends Betray You Silently

πŸ’‘ Lesson Learned — Not a Prod Bug, But a Real Pain No, this wasn’t a production outage. Nobody screamed at me. But I sat for 3 hours wondering: “Why the heck is my @Transactional not rolling back!?” 😡‍πŸ’« “Why is Redis cache not working?” 🀯 Turned out, the issue was one silent villain: 🧱 Self-invocation 🀷 What Is @Transactional ? If you're new: @Transactional = Tells Spring to start a DB transaction when a method is called. It’ll commit if everything’s okay. It’ll rollback if something fails. 🧠 Think of it like wrapping your code in: try { beginTransaction(); // your logic commit(); } catch(Exception e) { rollback(); } πŸ•΅️ Real-Life Analogy — The Gateway Community 🏘️ Let me tell you about my society — it has a strict watchman at the gate. Here’s how it works: πŸ›‚ Watchman = Spring Proxy 🏠 Your apartment = Your service class πŸšͺ Your room = A method inside that class πŸƒ Scenario 1: Outsider Visits Your friend from outside...

🧡 Virtual Threads in Java — The Ultimate Guide with Diagrams, Code & Interview Qs!

πŸš€ “How are Virtual Threads different from Thread Pools?” 😡 “Are they OS threads or JVM threads?” πŸ™ƒ “Should I still use CompletableFuture?” 🀯 “How do I even use them in real-time microservices?” 🧠 What are Virtual Threads? Virtual Threads (introduced in Java 21 as stable πŸŽ‰) are lightweight threads managed by the JVM instead of the OS kernel. πŸ‘‰ They look like normal threads, but don’t hog OS resources like traditional threads. 🧠 What is the OS Kernel? πŸ›️ OS Kernel = The Brain of the Operating System It’s the core part of your OS (Windows, Linux, Mac) that: Manages memory 🧠 Schedules threads πŸ•’ Talks to hardware πŸ’» Handles I/O operations πŸ“¨ When you create a traditional thread in Java, the JVM asks the OS Kernel to create a real OS-level thread. πŸ–Ό️ Imagine This... ┌───────────────────────────┐ │ Your Java Application │ └────────────┬──────────────┘ │ ...