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...

🌟 My Journey – From Zero to Senior Java Tech Lead 🌟

 There’s one thing I truly believe… If I can become a Java developer, then anyone in the world can. πŸ’― Sounds crazy? Let me take you back. πŸ•“ Back in 2015… I had zero coding knowledge . Not just that — I had no interest in coding either. But life has its own plans. In 2016, I got a chance to move to Bangalore and joined a Java course at a training center. That’s where it all started — Every day, every session made me feel like: "Ohhh! Even I can be a developer!" That course didn’t just teach Java — it gave me confidence . πŸ§ͺ Two Life-Changing Incidents 1️⃣ The Interview That Wasn't Planned Halfway through my course, I had to urgently travel to Chennai to donate blood to a family member. After that emotional rollercoaster, I found myself reflecting on my skills and the future. The next day, as I was preparing for my move to Bangalore to complete the remaining four months of my course, I randomly thought — "Let me test my skills... let me just see...