欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Springboot啟動類和啟動過程超詳細講解

 更新時間:2025年09月17日 09:14:08   作者:fixAllenSun  
springboot的啟動經(jīng)過了一些一系列的處理,下面這篇文章主要介紹了Springboot啟動類和啟動過程的相關資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下

【一】Spring Boot 啟動類的注解

Spring Boot 啟動類通常就是一個標注了 @SpringBootApplication的類,但這個注解是一個組合注解(Composite Annotation)?,理解它包含的元注解是關鍵。

【1】核心注解:@SpringBootApplication

這是啟動類上唯一必須的注解,它整合了三個核心注解的功能:

(1)?@SpringBootConfiguration?:Spring容器會從該類中加載Bean定義

(1)?作用?:表明當前類是一個配置類。它的底層是 @Configuration,這意味著Spring容器會從該類中加載Bean定義(@Bean注解的方法)。
(2)?為什么不用 @Configuration?:@SpringBootConfiguration是Spring Boot提供的,語義上更明確地指出這是主配置類,但在功能上與 @Configuration無異。

(2)?@EnableAutoConfiguration?:自動配置依賴

(1)?作用?:?啟用Spring Boot的自動配置機制。這是Spring Boot魔法(Convention over Configuration)的核心。
(2)?原理?:這個注解會通知Spring Boot根據(jù)你添加的jar包依賴(如classpath下是否存在DataSource、SpringMVC等類),自動猜測并配置你需要的Bean。例如,當你引入了spring-boot-starter-web,它會自動配置Tomcat和Spring MVC。

(3)?@ComponentScan?:?自動掃描并注冊Bean

(1)?作用?:?自動掃描并注冊Bean。默認會掃描啟動類所在包及其所有子包下的所有組件,包括@Component, @Service, @Repository, @Controller等注解的類,并將它們注冊到Spring容器中。
(2)?重要提示?:這是為什么通常要把啟動類放在項目根包(root package)下的原因。如果放在一個很深的包里,@ComponentScan可能無法掃描到其他重要的組件。

【2】其他常用注解(可根據(jù)需要添加)

雖然 @SpringBootApplication已經(jīng)足夠,但在某些場景下,你可能會在啟動類上額外添加一些注解。

(1)?@EnableScheduling?

?作用?:啟用Spring的定時任務功能。添加后,可以使用 @Scheduled注解來創(chuàng)建定時任務。

(2)?@EnableAsync?

?作用?:啟用Spring的異步方法執(zhí)行功能。添加后,可以使用 @Async注解來標記異步執(zhí)行的方法。

(3)?@EnableTransactionManagement?

?作用?:啟用注解式事務管理。不過,當Spring Boot檢測到存在事務管理器(如引入了JDBC或JPA starter)時,此功能實際上是默認開啟的。顯式添加此注解只是為了代碼意圖更清晰。

(4)?@EnableCaching?

?作用?:啟用Spring的注解驅動緩存功能。添加后,可以使用 @Cacheable, @CacheEvict等注解。

(5)?@Import?

?作用?:用于導入其他配置類(通常是@Configuration類),這些配置類可能不在@ComponentScan的掃描路徑下。例如:@Import({CustomConfig.class, AnotherConfig.class})。

?總結?:對于大多數(shù)標準應用,?只使用 @SpringBootApplication注解就足夠了。其他注解如 @EnableScheduling等,應根據(jù)具體功能需求選擇性添加。

【3】@MapperScan

@MapperScan注解的主要目的是告訴 MyBatis 應該去哪個或哪些包路徑下掃描 Mapper 接口,并自動將其注冊為 Spring 容器中的 Bean(MapperFactoryBean)?。

(1)?解決了什么問題???

在沒有這個注解之前,你需要在每個 Mapper 接口上手動添加 @Mapper注解,或者手動配置 MapperFactoryBean,非常繁瑣。@MapperScan通過包掃描的方式,實現(xiàn)了批量、自動的注冊,極大簡化了配置。

(2)?底層機制:??

當 Spring 容器啟動時,它會處理 @MapperScan注解。MyBatis-Spring 整合模塊會為指定的包路徑創(chuàng)建 ClassPathMapperScanner,該掃描器會找到所有接口,并為每個接口動態(tài)創(chuàng)建一個 MapperFactoryBean的 BeanDefinition 注冊到 Spring 容器中。MapperFactoryBean是一個 FactoryBean,它的 getObject()方法會使用 SqlSession為原始 Mapper 接口創(chuàng)建一個動態(tài)代理實例,并將這個代理實例作為 Bean 交給 Spring 管理。這就是為什么你可以在 Service 層直接 @Autowired一個接口的原因。

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import @SpringBootApplication

// 方式一:直接掃描一個包
@SpringBootApplication
@MapperScan("com.example.demo.mapper")
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

// 方式二:掃描多個包
@MapperScan(basePackages = {"com.example.mapper", "com.example.other.dao"})

// 方式三:類型安全的掃描(推薦)
// 創(chuàng)建一個空的標記接口,放在 com.example.mapper 包下
public interface MapperScanMarker {
    // 無任何方法,僅作為包路徑標記
}

@SpringBootApplication
// 掃描標記接口所在的包
@MapperScan(basePackageClasses = MapperScanMarker.class)
public class DemoApplication {
    // ...
}

【4】自動裝配原理

(1)自動裝配的核心思想

?要解決的問題:?? 傳統(tǒng) Spring 應用需要大量手動配置(如 XML、Java Config)來集成第三方庫或框架(例如數(shù)據(jù)源、事務管理器、MVC 等)。這個過程繁瑣且容易出錯。

?解決方案:?? Spring Boot 自動裝配通過預先定義的條件,在檢測到項目的特定依賴、配置和類路徑后,自動為應用注入所需的 Bean 并完成配置。簡單來說,就是 ??“如果我在類路徑上看到了 X,并且你沒有自己配置 Y,那么我就自動給你配置一個默認的 Y”?。

(2)實現(xiàn)原理的核心組件

(1)@SpringBootApplication與 @EnableAutoConfiguration

一切的起點是主啟動類上的 @SpringBootApplication注解。它是一個組合注解?(Composite Annotation),其核心功能之一由 @EnableAutoConfiguration提供。

@SpringBootApplication // 這是一個元注解,整合了其他注解的功能
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

@EnableAutoConfiguration本身又是一個開關注解,它通過 @Import導入了最核心的加載器:AutoConfigurationImportSelector。

(2)AutoConfigurationImportSelector

這個類是自動裝配的大腦。它的核心任務是決定需要導入哪些自動配置類。

?工作原理?:AutoConfigurationImportSelector會讀取項目 classpath 下所有 JAR 包中的 ?META-INF/spring.factories? 文件。

?關鍵文件?:在 spring-boot-autoconfigure-x.x.x.x.jar中,META-INF/spring.factories文件是一個鍵值對形式的配置文件。其中 EnableAutoConfiguration這個 key 后面列出了一長串的自動配置類(XXXAutoConfiguration)。

?spring.factories文件片段示例:??

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
# ... 省略上百個配置類
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration

AutoConfigurationImportSelector會獲取所有這些配置類的全限定名,并將它們作為候選配置類。

(3)@Conditional條件注解家族 - ?靈魂所在?

僅僅將候選配置類全部加載是不行的,Spring Boot 需要根據(jù)當前應用的環(huán)境來智能判斷哪些配置類應該真正生效。這就是 @Conditional系列注解的作用。

這些注解是自動裝配的“開關”,它們會在配置類或 Bean 被加載前進行條件判斷,只有滿足所有條件,配置才會生效。

(4)XXXAutoConfiguration自動配置類

這些是具體的執(zhí)行者。每個 XXXAutoConfiguration都是一個標準的 ?Spring 配置類?(@Configuration),其內部使用 @Bean方法來定義組件,并且方法上通常裝飾著各種 @Conditional注解。

【二】Spring Boot 項目啟動的詳細流程

Spring Boot 的啟動流程可以看作是傳統(tǒng) Spring 應用啟動流程的一個高度封裝和自動化版本。其核心是 SpringApplication.run(Application.class, args)方法。

以下是其詳細步驟:

【1】?啟動 Main 方法?

JVM 調用應用程序的 main方法。

【2】?創(chuàng)建 SpringApplication 實例?:

(1)在 run方法內部,首先會創(chuàng)建一個 SpringApplication實例。

(2)這個實例會進行一些初始化工作,例如:

1-?推斷應用類型?:判斷是普通的Servlet應用(Spring MVC)還是響應式Web應用(WebFlux)。

?2-初始化器(Initializers)??:加載 META-INF/spring.factories文件中配置的 ApplicationContextInitializer。

?3-監(jiān)聽器(Listeners)??:加載 META-INF/spring.factories文件中配置的 ApplicationListener(應用監(jiān)聽器)。這些監(jiān)聽器將用于接收整個啟動過程中發(fā)布的各種事件。

【3】?運行 SpringApplication 實例(run方法)??:這是最復雜的核心階段。

(1)?a. 啟動計時器 & 發(fā)布開始事件?:啟動一個計時器,并發(fā)布 ApplicationStartingEvent事件。此時容器還未創(chuàng)建,任何Bean都未初始化。

(2)?b. 準備環(huán)境(Environment)??:創(chuàng)建并配置應用運行環(huán)境(Environment),讀取所有配置源(application.properties/yaml、系統(tǒng)屬性、環(huán)境變量等)。發(fā)布 ApplicationEnvironmentPreparedEvent事件。

(3)?c. 創(chuàng)建應用上下文(ApplicationContext)??:根據(jù)第一步推斷的應用類型,創(chuàng)建對應的 ApplicationContext(例如,對于Servlet應用,創(chuàng)建 AnnotationConfigServletWebServerApplicationContext)。

(4)?d. 準備應用上下文?:

  • 將環(huán)境(Environment)設置到上下文中。
  • 執(zhí)行所有 ApplicationContextInitializer的 initialize方法,對上下文進行自定義初始化。
  • 發(fā)布 ApplicationContextInitializedEvent事件。

(5)?e. 刷新應用上下文(核心中的核心)??:調用上下文的 refresh()方法。這一步完成了傳統(tǒng)Spring應用容器的所有初始化工作:

  • ?加載Bean定義?:解析啟動類(因為它是@Configuration),執(zhí)行@ComponentScan掃描并注冊所有Bean定義。
  • ?執(zhí)行自動配置?:執(zhí)行 @EnableAutoConfiguration邏輯,加載 spring-boot-autoconfigurejar 包中 META-INF/spring.factories文件里的所有自動配置類(XXXAutoConfiguration),根據(jù)條件(@ConditionalOnXxx)判斷是否需要配置相應的Bean。
  • ?初始化Bean?:實例化所有非懶加載的單例Bean。

(6)?f. 后置處理?:執(zhí)行 CommandLineRunner和 ApplicationRunner接口的實現(xiàn)Bean。

(7)?g. 啟動完成?:發(fā)布 ApplicationStartedEvent事件,啟動計時器停止,打印啟動耗時日志。

整個流程伴隨著事件的發(fā)布,允許開發(fā)者通過監(jiān)聽這些事件在特定階段插入自定義邏輯。

【三】Spring Boot 生命周期中的擴展點及使用案例

Spring Boot 在整個生命周期中提供了大量“鉤子”(Hook),允許開發(fā)者介入并執(zhí)行自定義邏輯。以下是一些最重要的擴展點:

【1】Application Events(應用事件) - 觀察者模式

通過實現(xiàn) ApplicationListener接口或使用 @EventListener注解來監(jiān)聽特定事件。

?常用事件?:

  • ApplicationStartingEvent:應用剛啟動,任何處理都還未進行。
  • ApplicationEnvironmentPreparedEvent:環(huán)境已準備完畢,上下文還未創(chuàng)建。
  • ApplicationContextInitializedEvent:上下文已創(chuàng)建且初始化器已被調用,但Bean定義還未加載。
  • ApplicationPreparedEvent:Bean定義已加載,但Bean還未實例化。
  • ApplicationStartedEvent:上下文已刷新,所有Bean已實例化,CommandLineRunner/ApplicationRunner還未執(zhí)行。
  • ApplicationReadyEvent:應用已完全啟動,可以正常接收請求。

案例:在應用啟動成功后打印一條日志?java

import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class StartupNotifier {

    @EventListener(ApplicationReadyEvent.class)
    public void onAppReady() {
        System.out.println("?? Application is now ready and can serve traffic!");
        // 可以在這里執(zhí)行一些啟動后的檢查,比如檢查數(shù)據(jù)庫連接狀態(tài)等
    }
}

【2】ApplicationContextInitializer(應用上下文初始化器)

在 ApplicationContext刷新(refresh)之前,對其執(zhí)行自定義的初始化操作。

?案例:在上下文準備階段設置一個自定義屬性?java

import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;

public class MyInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        // 向環(huán)境中添加一個屬性
        applicationContext.getEnvironment().getSystemProperties().put("myCustomProperty", "initialized");
    }
}

?注冊方式?:需要在 META-INF/spring.factories文件中注冊。

復制org.springframework.context.ApplicationContextInitializer=com.example.MyInitializer

【3】CommandLineRunner / ApplicationRunner

在應用上下文刷新完成后、應用完全啟動之前,執(zhí)行一些特定的代碼。非常適合進行數(shù)據(jù)初始化、緩存預熱等操作。兩者功能幾乎一樣,區(qū)別在于參數(shù):

  • CommandLineRunner:提供原始的字符串數(shù)組參數(shù) String… args(即main方法的args)。
  • ApplicationRunner:提供更結構化的 ApplicationArguments對象來解析參數(shù)。

?案例:應用啟動后初始化一些數(shù)據(jù)?java

import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class DataLoader implements CommandLineRunner {

    private final UserRepository userRepository;

    public DataLoader(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public void run(String... args) throws Exception {
        // 檢查數(shù)據(jù)庫是否已有數(shù)據(jù),如果沒有則插入默認數(shù)據(jù)
        if (userRepository.count() == 0) {
            User admin = new User("admin", "admin@example.com");
            userRepository.save(admin);
            System.out.println("Initial admin user created.");
        }
    }
}

【4】Spring Bean 生命周期鉤子

這是 Spring 框架本身的擴展點,在 Spring Boot 中同樣適用。

  • @PostConstruct:在Bean的依賴注入完成后,初始化方法(InitializingBean.afterPropertiesSet)之前執(zhí)行。
  • InitializingBean接口:實現(xiàn) afterPropertiesSet()方法,在所有屬性設置完成后執(zhí)行。
  • @PreDestroy:在Bean被容器銷毀之前執(zhí)行。

?案例:Bean初始化后連接資源?java

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

@Component
public class ResourceConnector {

    @PostConstruct
    public void connect() {
        System.out.println("Connecting to external resource...");
        // 初始化連接
    }

    @PreDestroy
    public void disconnect() {
        System.out.println("Disconnecting from external resource...");
        // 關閉連接,釋放資源
    }
}

【四】Spring Bean 生命周期中的重要組件

【1】BeanPostProcessor (BPP) - 容器級后處理器?

(1)?作用?:這是Spring框架最強大、最核心的擴展接口。它作用于整個ApplicationContext,對所有Bean的初始化過程進行攔截和增強。你可以把它想象成一個“Bean加工流水線”。

(2)?兩個核心方法?:

  • 1-postProcessBeforeInitialization(Object bean, String beanName):在Bean的初始化回調方法?(如@PostConstruct)之前執(zhí)行。可以對Bean進行包裝或替換(例如返回一個代理對象,AOP就是基于此實現(xiàn)的)。
  • 2-postProcessAfterInitialization(Object bean, String beanName):在Bean的初始化回調方法之后執(zhí)行。此時Bean已基本完成初始化。

(3)?重要實現(xiàn)?:AutowiredAnnotationBeanPostProcessor(處理@Autowired注解)、CommonAnnotationBeanPostProcessor(處理@PostConstruct、@Resource等)、AnnotationAwareAspectJAutoProxyCreator(負責AOP動態(tài)代理)。

【2】BeanFactoryPostProcessor (BFPP) - 工廠級后處理器?

(1)?作用?:在Bean實例化之前,可以讀取、修改Bean的定義(BeanDefinition)。它操作的是“藍圖”,而不是Bean實例本身。

(2)?核心方法?:postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)

(3)?經(jīng)典案例?:PropertySourcesPlaceholderConfigurer(處理 ${…}占位符)就是在此時將Bean定義中的占位符替換為實際的屬性值。

【3】Aware 接口族 - 感知接口?

?(1)作用?:讓Bean能“感知”到容器本身和某些特定的資源。這些接口的回調發(fā)生在BeanPostProcessor之前,初始化方法之后。

(2)?常用接口?:

  • 1-BeanNameAware:感知自己在容器中的Bean名稱。
  • 2-ApplicationContextAware:感知自己所在的ApplicationContext(這是手動獲取Bean的一種方式)。
  • 3-BeanFactoryAware:感知創(chuàng)建自己的BeanFactory。

【4】生命周期回調注解/接口?

(1)?作用?:定義Bean自身初始化和銷毀時的行為。

(2)?初始化?:

  • ?JSR-250注解?:@PostConstruct(推薦使用,標準注解)。
  • ?Spring接口?:InitializingBean及其 afterPropertiesSet()方法。
  • ?XML配置?:init-method屬性。

(3)?銷毀?:

  • ?JSR-250注解?:@PreDestroy(推薦使用)。
  • ?Spring接口?:DisposableBean及其 destroy()方法。
  • ?XML配置?:destroy-method屬性。

【5】生命周期執(zhí)行順序

?執(zhí)行順序?:BeanFactoryPostProcessor-> BeanPostProcessor的Before-> Aware接口 -> @PostConstruct-> InitializingBean-> init-method-> BeanPostProcessor的After-> … -> @PreDestroy-> DisposableBean-> destroy-method。

總結

到此這篇關于Springboot啟動類和啟動過程的文章就介紹到這了,更多相關Springboot啟動類和啟動過程內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Jenkins與SVN持續(xù)集成的示例代碼

    Jenkins與SVN持續(xù)集成的示例代碼

    這篇文章主要介紹了Jenkins與SVN持續(xù)集成的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • Java集合List的使用詳細解析

    Java集合List的使用詳細解析

    這篇文章主要介紹了Java集合List的使用詳細解析,List集合類中元素有序、且可重復,集合中的每個元素都有其對應的順序索引,鑒于Java中數(shù)組用來存儲數(shù)據(jù)的局限性,我們通常使用java.util.List替代數(shù)組,需要的朋友可以參考下
    2023-11-11
  • SpringBoot中并發(fā)定時任務的實現(xiàn)、動態(tài)定時任務的實現(xiàn)(看這一篇就夠了)推薦

    SpringBoot中并發(fā)定時任務的實現(xiàn)、動態(tài)定時任務的實現(xiàn)(看這一篇就夠了)推薦

    這篇文章主要介紹了SpringBoot并發(fā)定時任務動態(tài)定時任務實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-04-04
  • java學習之JasperReport踩坑

    java學習之JasperReport踩坑

    本篇文章介紹的是在JAVA學習中JasperReport遇到的坑以及解決辦法,有需要的朋友參考下吧。
    2018-01-01
  • JSON序列化Redis讀取出錯問題解決方案

    JSON序列化Redis讀取出錯問題解決方案

    這篇文章主要介紹了JSON序列化Redis讀取出錯問題解決方案,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-09-09
  • Java使用WeakHashMap實現(xiàn)緩存自動清理

    Java使用WeakHashMap實現(xiàn)緩存自動清理

    在 Java 中,內存管理是一個重要的話題,尤其是在涉及到緩存的實現(xiàn)時,如果緩存項不再被使用,我們希望它們能被自動清理,而不必手動刪除,WeakHashMap 就是 Java 提供的一種用于緩存和內存管理的工具,本文將深入探討如何利用 WeakHashMap 來實現(xiàn)緩存自動清理
    2025-01-01
  • Java8處理集合的優(yōu)雅姿勢之Stream

    Java8處理集合的優(yōu)雅姿勢之Stream

    這篇文章主要給大家介紹了關于Java8優(yōu)雅處理集合之Stream的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者使用java8具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-03-03
  • java獲取服務器基本信息的方法

    java獲取服務器基本信息的方法

    這篇文章主要介紹了java獲取服務器基本信息的方法,涉及java獲取系統(tǒng)CPU、內存及操作系統(tǒng)等相關信息的技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-07-07
  • 如何在Springboot實現(xiàn)攔截器功能

    如何在Springboot實現(xiàn)攔截器功能

    其實spring boot攔截器的配置方式和springMVC差不多,只有一些小的改變需要注意下就ok了,下面這篇文章主要給大家介紹了關于如何在Springboot實現(xiàn)攔截器功能的相關資料,需要的朋友可以參考下
    2022-06-06
  • Java多線程之CAS算法實現(xiàn)線程安全

    Java多線程之CAS算法實現(xiàn)線程安全

    這篇文章主要介紹了java中如何通過CAS算法實現(xiàn)線程安全,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,下面小編和大家一起來學習一下吧
    2019-05-05

最新評論