初始化源碼
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {~~~setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));~~~
}private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {// 獲取當前 SpringApplication 實例的類加載器// 這個類加載器將用于加載類和資源ClassLoader classLoader = getClassLoader();// 從 META-INF/spring.factories 文件中加載指定類型的工廠類名稱// 使用 LinkedHashSet 保證加載的類名稱的順序,并且去除重復項// SpringFactoriesLoader.loadFactoryNames(type, classLoader) 會讀取 spring.factories 文件中指定類型的類名稱Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));// 根據加載的類名稱,反射創建指定類型的實例// createSpringFactoriesInstances 方法會根據類名稱和構造函數參數類型及參數值,反射創建實例List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);// 根據 @Order 注解或實現 Ordered 接口的順序對實例進行排序// AnnotationAwareOrderComparator.sort(instances) 會根據 @Order 注解或 Ordered 接口的值對實例進行排序AnnotationAwareOrderComparator.sort(instances);// 返回創建并排序后的實例集合return instances;
}
SpringApplication中 initializers
鉤子實現
1. 實現 ApplicationContextInitializer
接口
你需要創建一個類,實現 ApplicationContextInitializer
接口,并在 initialize
方法中實現自定義的初始化邏輯。
public class MyApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {@Overridepublic void initialize(ConfigurableApplicationContext applicationContext) {// 在這里執行自定義邏輯System.out.println("Executing custom logic before Spring context refresh");// 例如,設置環境變量ConfigurableEnvironment environment = applicationContext.getEnvironment();environment.setProperty("custom.property", "customValue");}
}
2. 注冊初始化器
你可以在 SpringApplication
的構造方法中顯式注冊這些初始化器,或者通過 META-INF/spring.factories
文件自動發現它們。
顯式注冊
在 SpringApplication
的構造方法中顯式注冊初始化器:
public class MyApplication {public static void main(String[] args) {SpringApplication application = new SpringApplication(MyApplication.class);// 顯式注冊初始化器application.addInitializers(new MyApplicationContextInitializer());application.run(args);}
}
通過 META-INF/spring.factories
文件自動發現
在 resources
目錄下創建或編輯 META-INF/spring.factories
文件,并添加你的初始化器類:
org.springframework.context.ApplicationContextInitializer=\
com.example.MyApplicationContextInitializer
初始化器的執行順序
ApplicationContextInitializer
:在 Spring 容器刷新之前執行。ApplicationRunner
和CommandLineRunner
:在 Spring 容器刷新之后執行。
ApplicationListener
是 Spring 提供的一個接口,用于監聽 Spring 應用上下文中的事件。通過實現ApplicationListener
接口,你可以捕獲并處理特定的事件,從而在 Spring 應用的生命周期中執行自定義邏輯。
以下是使用 ApplicationListener
鉤子的步驟和示例代碼:
SpringApplication中listeners 鉤子實現
ApplicationListener接口繼承自Java的EventListener接口,表示一個事件監聽器,它能夠接收并處理特定類型的事件。在Spring中,當一個事件被發布時(通常是通過ApplicationContext的publishEvent方法),Spring會查找所有實現了ApplicationListener接口并且聲明了要監聽的事件類型的Bean,然后調用這些Bean的onApplicationEvent方法來處理事件。
1. 實現 ApplicationListener
接口
你需要創建一個類,實現 ApplicationListener
接口,并重寫 onApplicationEvent
方法。onApplicationEvent
方法會在事件發生時被調用。
示例代碼
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;@Component
public class MyApplicationListener implements ApplicationListener<ApplicationReadyEvent> {@Overridepublic void onApplicationEvent(ApplicationReadyEvent event) {// 在這里執行自定義邏輯System.out.println("Application is ready and fully started!");// 你可以在這里執行一些初始化邏輯或檢查}
}
2. 監聽特定事件
Spring 提供了多種事件類型,例如:
ContextRefreshedEvent
:在 Spring 容器刷新時觸發。ApplicationReadyEvent
:在 Spring 應用完全啟動后觸發。ContextStartedEvent
:在 Spring 容器啟動時觸發。ContextStoppedEvent
:在 Spring 容器停止時觸發。ContextClosedEvent
:在 Spring 容器關閉時觸發。
你可以選擇監聽特定的事件類型。例如,如果你想在應用啟動后執行一些邏輯,可以監聽 ApplicationReadyEvent
。
3. 自定義事件
你還可以定義自己的事件類型,并在需要的時候發布這些事件。
定義自定義事件
import org.springframework.context.ApplicationEvent;public class MyCustomEvent extends ApplicationEvent {private String message;public MyCustomEvent(Object source, String message) {super(source);this.message = message;}public String getMessage() {return message;}
}
發布自定義事件
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;@Service
public class MyService {@Autowiredprivate ApplicationEventPublisher eventPublisher;public void doSomething() {// 執行一些業務邏輯System.out.println("Doing something...");// 發布自定義事件MyCustomEvent customEvent = new MyCustomEvent(this, "Custom event message");eventPublisher.publishEvent(customEvent);}
}
監聽自定義事件
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;@Component
public class MyCustomEventListener implements ApplicationListener<MyCustomEvent> {@Overridepublic void onApplicationEvent(MyCustomEvent event) {// 在這里處理自定義事件System.out.println("Received custom event: " + event.getMessage());}
}
4. 使用注解方式監聽事件
除了實現 ApplicationListener
接口,你還可以使用 @EventListener
注解來監聽事件。