Understanding Spring Boot Startup: @SpringBootApplication, Core Annotations, and Auto‑Configuration Process
This article explains the inner workings of a Spring Boot application startup class, detailing the composite @SpringBootApplication annotation, the roles of @Configuration, @ComponentScan, and @EnableAutoConfiguration, and walks through the SpringApplication execution flow and the auto‑configuration mechanism powered by SpringFactoriesLoader.
Source: www.cnblogs.com/xiaoxi/p/7999885.html
In every Spring Boot project we usually start with the following boot class:
@SpringBootApplication
public
class
Application
{
public
static
void
main
(String[] args) {
SpringApplication.run(Application.class, args);
}
}From the code above the most eye‑catching parts are the annotation @SpringBootApplication and the class method call SpringApplication.run , so we will start uncovering Spring Boot from these two elements.
1. The secret behind @SpringBootApplication
@SpringBootApplication is the core annotation of Spring Boot; it is actually a composite annotation:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public
@interface
SpringBootApplication {
...
}Although many annotations are used for meta‑information, only three are essential:
@Configuration (which itself includes @SpringBootConfiguration that again uses @Configuration )
@EnableAutoConfiguration
@ComponentScan
In other words, @SpringBootApplication = @Configuration + @EnableAutoConfiguration + @ComponentScan .
Therefore, using the three annotations directly yields the same functionality as the single @SpringBootApplication .
@Configuration
@EnableAutoConfiguration
@ComponentScan
public
class
Application
{
public
static
void
main
(String[] args) {
SpringApplication.run(Application.class, args);
}
}Writing the three annotations each time is tedious, so we usually keep the single @SpringBootApplication .
1. @Configuration
@Configuration is familiar to us; it marks a Java class as a Java‑Config style Spring IoC container configuration class. Spring Boot recommends using Java‑Config, so the boot class is also a configuration class.
A quick comparison between XML‑based configuration and Java‑Config:
(1) Expression level
XML configuration looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
default-lazy-init="true">
</beans>Java‑Config looks like this:
@Configuration
public
class
MockConfiguration
{
// bean definitions
}Any Java class annotated with @Configuration is a Java‑Config configuration class.
(2) Bean registration level
XML registration:
<bean id="mockService" class="..MockServiceImpl">
...
</bean>Java‑Config registration:
@Configuration
public
class
MockConfiguration
{
@Bean
public
MockService mockService() {
return new MockServiceImpl();
}
}Any method annotated with @Bean returns an object that will be registered as a bean in the Spring IoC container; the method name becomes the bean id.
(3) Dependency injection level
In XML the dependency between beans is expressed like this:
<bean id="mockService" class="..MockServiceImpl">
<property name="dependencyService" ref="dependencyService"/>
</bean>
<bean id="dependencyService" class="DependencyServiceImpl"/>Java‑Config expresses the same relationship as:
@Configuration
public
class
MockConfiguration
{
@Bean
public
MockService mockService() {
return new MockServiceImpl(dependencyService());
}
@Bean
public
DependencyService dependencyService() {
return new DependencyServiceImpl();
}
}The @Configuration annotation works together with @Bean to create a simple Java‑Config class that can replace the equivalent XML configuration.
<beans>
<bean id="car" class="com.test.Car">
<property name="wheel" ref="wheel"/>
</bean>
<bean id="wheel" class="com.test.Wheel"/>
</beans>Equivalent Java‑Config:
@Configuration
public
class
Conf
{
@Bean
public
Car car() {
Car car = new Car();
car.setWheel(wheel());
return car;
}
@Bean
public
Wheel wheel() {
return new Wheel();
}
}2. @ComponentScan
@ComponentScan is important in Spring; it automatically scans and loads components such as @Component, @Repository, etc., that match the criteria, effectively replacing the XML <context:component-scan> element.
The scan range can be fine‑tuned with attributes like basePackages . If not specified, Spring scans the package of the class where @ComponentScan is declared.
Note: Therefore the Spring Boot main class should be placed in the root package because the default scan starts from the package of the class containing @ComponentScan.
3. @EnableAutoConfiguration
Personally I think @EnableAutoConfiguration is the most important annotation, and it follows the same pattern as other @Enable* annotations such as @EnableScheduling, @EnableCaching, @EnableMBeanExport, etc. It works by using @Import to collect and register bean definitions that match the current scenario.
For example, @EnableScheduling imports all scheduling‑related beans, @EnableMBeanExport imports JMX beans, and @EnableAutoConfiguration imports all auto‑configuration beans that satisfy the conditions.
When a spring-boot-starter-web dependency is present, @EnableAutoConfiguration automatically adds Tomcat and Spring MVC configurations.
The definition of @EnableAutoConfiguration (a composite annotation) is as follows:
@SuppressWarnings("deprecation")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public
@interface
EnableAutoConfiguration {
...
}The key part is @Import(EnableAutoConfigurationImportSelector.class) . This selector uses SpringFactoriesLoader to load all @Configuration classes that match the current classpath and registers them into the IoC container.
SpringFactoriesLoader is a private Spring extension that loads configuration from META-INF/spring.factories files on the classpath.
public
abstract
class
SpringFactoriesLoader {
// ...
public
static <T> List<T> loadFactories(Class<T> factoryClass, ClassLoader classLoader) {
...
}
public
static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
...
}
}When used together with @EnableAutoConfiguration, SpringFactoriesLoader finds all META-INF/spring.factories files, reads the key org.springframework.boot.autoconfigure.EnableAutoConfiguration , and obtains a list of configuration class names.
2. Deep dive into SpringApplication execution flow
The run method of SpringApplication is the main entry point of the boot process. Its overall steps are:
If SpringApplication.run is called statically, a SpringApplication instance is created first. Detect whether a web environment is needed by checking for org.springframework.web.context.ConfigurableWebApplicationContext on the classpath. Use SpringFactoriesLoader to load all ApplicationContextInitializer implementations. Use SpringFactoriesLoader to load all ApplicationListener implementations. Determine and set the main class.
After initialization, the run method proceeds: Iterate over all SpringApplicationRunListener instances loaded via SpringFactoriesLoader and invoke their started() method. Create and configure the Environment (property sources, profiles, etc.). Notify listeners with environmentPrepared() . Print the banner if enabled. Determine the concrete ApplicationContext class (web vs. non‑web) and instantiate it. Associate listeners, environment, arguments, and banner with the context. Load all ApplicationContextInitializer via SpringFactoriesLoader and invoke initialize() on the context. Notify listeners with contextPrepared() and later contextLoaded() . Refresh the context (bean creation, post‑processing, etc.). Execute any CommandLineRunner beans. Finally invoke finished() on all listeners (or on error).
The article uses a real Spring Boot startup example to illustrate the above steps and the underlying auto‑configuration mechanism.
Overview
The startup structure can be divided into three parts:
Initialization of SpringApplication (environment, resources, constructors, listeners).
Implementation of the concrete startup scheme (listeners, environment loading, context creation).
Auto‑configuration module, the core of Spring Boot auto‑configuration.
Startup
Every Spring Boot program has a main method that calls SpringApplication.run() . The class containing this method must be annotated with @SpringBootApplication (and optionally @ImportResource ). The three annotations inside @SpringBootApplication provide:
@EnableAutoConfiguration : automatically configures Spring based on declared dependencies.
@SpringBootConfiguration (internally @Configuration ): assembles all bean definitions, providing the Spring context.
@ComponentScan : scans the package of the boot class for components, so the boot class should be placed in the root package.
Spring Boot startup class
First, the run method creates a SpringApplication instance.
Inside the constructor, an initialize method is called to set default values.
After the constructor finishes, control returns to the run method.
The method implements the following key steps:
Create SpringApplicationRunListeners and start listening.
Load the Spring Boot configuration environment ( ConfigurableEnvironment ).
Associate listeners, environment, application arguments, and banner with the context.
Create the ConfigurableApplicationContext (defaulting to AnnotationConfigApplicationContext for non‑web apps).
Prepare the context by linking listeners, environment, and arguments.
Refresh the context, which triggers auto‑configuration via spring.factories and bean instantiation.
After configuration, Spring Boot performs final steps and returns the application context. In summary, Spring Boot startup creates the environment, listeners, and application context, then instantiates the required beans, completing the boot process.
Auto‑configuration
The auto‑configuration module, highlighted in the earlier diagram, relies heavily on SpringFactoriesLoader to load spring.factories files from all dependencies (e.g., mybatis‑spring‑boot‑starter, spring‑boot‑starter‑web) and instantiate the listed configuration classes.
Spring Boot auto‑configuration module
The module uses SpringFactoriesLoader to load class names from META-INF/spring.factories . The loader returns a list of class names, which are then instantiated via reflection to become concrete factories that generate the beans required by each starter.
Factory interface and its implementations
The diagram below illustrates how EnableAutoConfiguration ultimately uses AutoConfigurationImportSelector to select configuration classes based on the classpath.
Spring Boot auto‑configuration key component relationship
Starters such as mybatis-spring-boot-starter and spring-boot-starter-web contain spring.factories files. SpringFactoriesLoader reads these files, obtains the fully‑qualified class names, and instantiates them, which in turn registers the necessary beans.
The definition of @EnableAutoConfiguration shows it implements ImportSelector and BeanClassLoaderAware . The crucial method selectImports of AutoConfigurationImportSelector returns the list of configuration classes to be imported.
The selector loads candidate configurations via loadFactoryNames , which reads spring.factories entries for the key EnableAutoConfiguration . For example, the MyBatis starter provides org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration .
The MyBatis auto‑configuration class is annotated with @Configuration and conditional annotations such as @ConditionalOnClass (requires SqlSessionFactory and SqlSessionFactoryBean ) and @ConditionalOnBean(DataSource.class) . When the conditions are satisfied, beans like sqlSessionFactory , sqlSessionTemplate , and dataSource are automatically configured.
By simply adding the appropriate starter dependency, the required classes appear on the classpath, triggering the conditional auto‑configuration without any manual XML configuration.
This demonstrates how Spring Boot abstracts away extensive XML configuration and complex dependency management, allowing developers to focus on business logic.
(End)
Java Leader
Focused on Java knowledge sharing
Scan the QR code above for more Java content
Java Captain
Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.