Spring Boot for Real-World Development: No Confusion
Making Java into Powerful Apps That Are Ready for Production

What is Spring Boot?
Spring Boot is a framework built on the Spring Framework. It simplifies setup by removing most of the repetitive configuration, allowing you to create ready-to-use applications quickly.
Main promises:
Spring Boot automatically sets up common components like web servers and databases based on the JAR files you include.
You can run the app with java -jar myapp.jar without needing an external Tomcat.
Starter dependencies mean that adding one dependency, like spring-boot-starter-web, brings in all needed libraries such as Spring MVC, Jackson, and embedded Tomcat.
No more web.xml, no more applicationContext.xml—just use Java code and annotations.
The Main Class: @SpringBootApplication
Every Spring Boot app has a main class marked with @SpringBootApplication.
@SpringBootApplication combines three annotations**:**
| Annotation | Purpose |
|---|---|
@SpringBootConfiguration |
Marks the class as a configuration source, like @Configuration. You can define @Bean methods in it. |
@EnableAutoConfiguration |
Spring Boot automatically sets up components based on the libraries you include. |
@ComponentScan |
Looks through the package of the class with the annotation (and its sub-packages) to find @Component, @Service, @Repository, @Controller, and registers them as beans. |
Visual: @SpringBootApplication = @SpringBootConfiguration + @EnableAutoConfiguration + @ComponentScan
How @EnableAutoConfiguration works – a simple example
When you add spring-boot-starter-web to your pom.xml, Spring Boot automatically:
Starts a built-in Tomcat on port 8080
Adds a DispatcherServlet
Sets up Jackson for converting data to and from JSON.
Sets up default error pages and more.
You already have a working web server without writing any code. If you add spring-boot-starter-data-jpa and a database driver, it will automatically set up a DataSource, an EntityManagerFactory, and a TransactionManager.
Rule: Auto‑configuration is conditional. If you define your own DataSource bean, the auto‑configured one backs off (@ConditionalOnMissingBean).
Behind the Scenes: SpringApplication.run()
The line SpringApplication.run(DemoApplication.class, args) starts everything. Here's what happens step by step:
Step-by-step internal workflow Step Description
Create a SpringApplication instance. It checks if the app is servlet-based (if Servlet is available), reactive, or neither.
It loads configuration settings from application.properties, application.yml, environment variables, and command line arguments.
Create the ApplicationContext (IoC container). For a web app, it makes an AnnotationConfigServletWebServerApplicationContext.
Run @ComponentScan: The context looks through the main class's package and registers all classes with stereotype annotations as beans.
Call @EnableAutoConfiguration. Spring loads all auto-configuration classes. Each class can create beans if certain conditions are met.
The embedded web server, like Tomcat, Jetty, or Undertow, starts on the set port, usually 8080.
Run CommandLineRunner or ApplicationRunner beans. These beans execute once the context is ready, which is helpful for startup tasks.
Your application is now running and handling requests. SpringApplication.run() gives you the ApplicationContext, which contains all the beans. You usually don't need to use it directly, but you can access a bean if needed.
Beans and the IoC Container – Basics + Code
What is a bean?
A bean is a Java object created, managed, and connected by the Spring IoC container. You don't create it with new keyword ; Spring provides the instance.
The IoC (Inversion of Control) container is a map of beans. It manages:
The IoC container creates beans, usually as singletons by default.
Dependency injection (wiring)
Destruction occurs when the application shuts down.
Declare beans using @Component, @Service, and similar annotations.
Thanks to @ComponentScan (inside @SpringBootApplication), Spring locates this class, creates an instance, and places it in the container as "applePay"
Other stereotypes, all marked with @Component:
@Serviceis used for business logic.@Repositoryis used for data access and helps translate persistence exceptions.@Controllerand@RestControllerare used for web endpoints.
Dependency Injection – constructor injection example
Instead of manually creating dependencies, you ask Spring to inject them.
Constructor injection is recommended because it makes dependencies clear and ensures that objects are fully initialized. It also supports immutability and makes testing easier.
The class cannot be changed (final fields).
Easier to test because you can pass a mock argument to the constructor.
You don't need to use @Autowired for a single constructor since Spring 4.3+.
A Complete REST API Example
Let's create a simple REST controller.
Explanation:
@RestControllercombines@Controllerand@ResponseBody, meaning every method returns data instead of a view.@GetMapping("/hello")connectsHTTP GETrequests to this method
Start the application, open your browser, go to http://localhost:8080/hello, and you'll see "Hello, Spring Boot!".
No XML, no web.xml, no servlet setup. That's the strength of Spring Boot.
The "Multiple Beans" Error
You noticed this in your log:
It happens because Spring finds more than one bean of the same type, and it doesn't know which one to use.
You have two beans doing the same job, and you're trying to use the interface type without telling Spring which one to choose.
Three ways to fix it
- Mark one bean as
@Primary
Now, when PaymentService is needed, Spring automatically uses ApplePay.
- Use
@Qualifierto specify the bean name
The qualifier value is the bean name, usually the class name in lower camel case You can also give it a custom name using @Component("myName") .
- Inject a
Listof all beans of that type
You can loop through all implementations or choose one as needed.
Why you need the -parameters compiler flag
If you use constructor injection without @Autowired and want Spring to match parameters by name instead of just by type, you need the -parameters flag.
The parameter is called applePay. Without the -parameters flag, the compiler ignores parameter names, so Spring can't match applePay to the bean named applePay. It then tries to match by type, which fails if there are multiple options.
How to enable it:
Maven (pom.xml):
- IntelliJ IDEA:
Settings → Build, Execution, Deployment → Compiler → Java Compiler →
Additional command line parameters: → add -parameters
When enabled, Spring can use parameter names to tell beans apart, and the error might go away even without @Qualifier, as long as the parameter name matches a bean name.
Putting It All Together – Functional Code
Here is a complete, runnable example that includes the multiple‑bean fix.
Run it: GET http://localhost:8080/pay → Response: Apple Pay If you take out @Primary and add @Qualifier("payPal") in the controller constructor, the response will be "PayPal".
Where to go next:
Spring Data JPA – use repositories to work with databases
Spring Security – add login and access control
Spring Boot Actuator – monitor and check health
Spring Cloud – create microservices
Now go and create something amazing with Spring Boot! If you encounter the "multiple beans" error again, you'll know how to solve it.





