When I’m learning a new framework, I like to look at things that beginners don’t like to read or don’t understand. For example, when I was learning Angular, it was obvious that ng new would be enough to create a new project and start writing programs, but I would go deeper into the whole process of starting it. And when I was learning Spring Boot, even though Spring Initializr was really nice to use, and I could start developing applications by just selecting the packages, I wanted to understand what was going on behind the scenes of this amazing design, so I could understand the core principles of a framework.
In this article, we will explore the principles of @SpringBootApplication, a core annotation in Spring Boot.

Create sample applications
-
Quickly building a project using the Spring Boot CLI
1spring init --dependencies=web,lombok --groupId=com.duotify starter1It can also be created with Spring Initializr
-
Open the project using Visual Studio Code
1code starter1/
The current folder and file structure of the project is as follows.
|
|
Application entry points
All Java applications need an entry point to run, so you just need to find the class that contains the main() method, which is our entry point.
|
|
There is a @SpringBootApplication annotation on this class that declares that this is a Spring Boot application. But this @SpringBootApplication annotation itself has several annotations applied to it, so we can see the source code by pressing F12.
|
|
From the above code, we can find three other important annotations.
-
@SpringBootConfigurationThis
@SpringBootConfigurationannotation is mainly used to add@Configurationannotation to current class (DemoApplication), you can take a look at the source code part of@SpringBootConfiguration, he has a@Configurationannotation applied to it.You can actually apply the
@Configurationannotation directly toDemoApplication, but the semantics of applying@SpringBootConfigurationis much clearer and more readable! 👍Basically, applying the
@Configurationannotation will allow theDemoApplicationclass to be added to the Spring IoC container, and if there is a Method (Method) in the class with the@Beanannotation, that method can be executed by Spring Boot at application startup. and the object returned by the method is added to the Spring IoC container so that other components (@Component) can be used by constructive injection, attribute injection (@Autowired) or method injection (@Qualifier).This is a manual process of creating and registering Spring Bean components.
-
@EnableAutoConfigurationThe
@EnableAutoConfigurationannotation first allows Spring Boot to automatically find all classes in the dependent package that have@Componentannotations applied to them through the@ComponentScandefinition, and automatically create and register them as Spring bean components. This process is like automatically adding@Configurationannotations to these classes for you.Dependent packages such as
TomcatorSpring MVChave a similar design, so using@EnableAutoConfigurationcan greatly simplify the amount of code. -
@ComponentScanThis
@ComponentScanannotation is used to automatically scan the currentpackageand allsub-packageclasses annotated with the@Componentannotation and provide them to@EnableAutoConfigurationfor automatic configuration. This process is also known as Component scanning.These three tags are important because they serve different and related purposes. In general,
@EnableAutoConfigurationand@SpringBootConfigurationwill only be applied once to the root class, and@ComponentScanwill usually only be applied to the root class. But if you have other libraries, you can decide for yourself if you want to use@ComponentScanto find all the classes under the current class package and sub-packages that have@Componentannotated.Note: Generally speaking, fewer people apply
@Componentannotations directly to classes, instead using annotations that inherit from@Component.@Controller,@Service,@Repository,@Configurationare all such annotations. Since@RestControllerinherits from@Controller, this is also a type of Stereotype Annotations.
Normally, you can just use the @SpringBootApplication annotation on the root class and ignore the underlying technical details in 99% of the cases.
Demonstrate several different application scenarios
-
There is only one class for the whole application, no need for
@ComponentScanto automatically scansub-packages.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21package com.duotify.starter1; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @EnableAutoConfiguration public class DemoApplication { @RequestMapping("/") String home() { return "Hello World!123"; } public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }Such examples are relatively rare and are mostly found in code examples that you will see when you first learn the Spring Boot framework.
The
@EnableAutoConfigurationannotation here automatically configures all Spring beans, but we don’t apply@ComponentScan, so it doesn’t automatically scan thecom.dootify.starter1andcom.dootify.starter1.*classes.Here is the
@RestControllerannotation, whose source code looks like this, which contains the@Controllerand@ResponseBodyannotations.And the source code of the
@Controllerannotation looks like this.So in fact, he has applied
@Component, so it will be automatically set by@EnableAutoConfigurationannotation, so the DemoApplication class itself will be registered as a Spring bean component, so it can be executed directly as a Controller. -
There is more than one class for the whole application, we want to split the Controller class and write it separately, so we need
@ComponentScanto automatically scan the classes insub-packagesI’ll start by changing
DemoApplication.javato this.1 2 3 4 5 6 7 8 9 10 11 12 13package com.duotify.starter1; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; @EnableAutoConfiguration public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }Then add a
com.dootify.starter1.controllers.HomeControllerclass.1 2 3 4 5 6 7 8 9 10 11 12package com.duotify.starter1.controllers; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HomeController { @RequestMapping("/") String home() { return "Hello World!"; } }After launching the application, the
HomeControllercontroller will not be found because it is not registered as a Spring Bean component.We add the
@ComponentScanannotation to theDemoApplicationclass ofDemoApplication.java.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15package com.duotify.starter1; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.ComponentScan; @EnableAutoConfiguration @ComponentScan public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }Restart the application and you can call the API without any problem!
-
We have a common object that is registered via
@Beanand used by other components that are also registered in the Spring IoC container.Because all classes annotated with
@Componentwill eventually be registered in the Spring IoC container. And all the components registered to Spring IoC container can be injected into other components. So we can add a Spring bean method to theDemoApplicationclass.Once added, the
appName()method, which has the@Beanannotation, does not actually run automatically when the Spring Boot application starts unless you apply the@Configurationannotation to theDemoApplicationclass.The result is as follows.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23package com.duotify.starter1; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @EnableAutoConfiguration @ComponentScan @Configuration public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } @Bean(name = "appName") public String appName() { return "Starter1"; } }Since we have collected the
@EnableAutoConfiguration,@ComponentScan,@Configurationannotations, we can now merge them directly into the@SpringBootApplicationannotation.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21package com.duotify.starter1; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } @Bean(name = "appName") public String appName() { return "Starter1"; } }Finally, we modify the
HomeControllerclass and use the constructive injectionStringSpring bean to use it.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19package com.duotify.starter1.controllers; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HomeController { private String appName; public HomeController(String appName) { this.appName = appName; } @RequestMapping("/") String home() { return "Hello " + this.appName + "!"; } }If you want to use “attribute injection”, you can also use
@Autowiredin the fields and the code will be simpler.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17package com.duotify.starter1.controllers; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HomeController { @Autowired private String appName; @RequestMapping("/") String home() { return "Hello " + this.appName + "!"; } }Testing.
Conclusion
In fact, this article has covered many basics, including
- Spring Initializr
- Spring Boot CLI
- Using the @SpringBootApplication Annotation
@SpringBootApplication@EnableAutoConfiguration@ComponentScan(Spring Component Scanning)@SpringBootConfiguration@Configuration
- Spring Stereotype Annotations
@Component@Controller@RestController
@Service@Compoment@Repository@Configuration
- Spring IoC Container
Because these are the core mechanisms of Spring, as long as you can understand the above concepts completely, you can understand the other parts very well! 👍
Related links
- Difference Between @ComponentScan and @EnableAutoConfiguration in Spring Boot | Baeldung
- Spring Component Scanning | Baeldung
- What is a Spring Bean? | Baeldung
- Spring Boot Change Context Path | Baeldung
Reference https://blog.miniasp.com/post/2022/09/20/How-Spring-Boot-Works