SpringBoot系列-SpringApplication

自定義 SpringApplication

SpringApplication

SpringApplication Spring Boot 驅動 Spring 應用上下文的引導類web

@SpringBootConfiguration@EnableAutoConfiguration@ComponentScan(excludeFilters = {    @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),    @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })public @interface SpringBootApplication {    ...}複製代碼

@ComponentScan: 它是版本引入的? Spring Framework 3.1spring

@EnableAutoConfiguration: 激活自動裝配 @Enable -> @Enable 開頭的編程

  • @EnableWebMvcbash

  • @EnableTransactionManagementapp

  • @EnableAspectJAutoProxy框架

  • @EnableAsyncide

@SpringBootConfiguration : 等價於 @Configuration -> Configuration Class 註解spring-boot

@Component 的「派生性」

@Component -> @ComponentScan性能

處理類 -> ConfigurationClassParser單元測試

掃描類 ->

  • ClassPathBeanDefinitionScanner

    • ClassPathScanningCandidateComponentProvider

      protected void registerDefaultFilters() {    this.includeFilters.add(new AnnotationTypeFilter(Component.class));      ...  }複製代碼

      Dubbo @Service -> 2.5.7 -> new AnnotationTypeFilter(Service.class);

Spring 註解編程模型

  • @Component

    • @Service

      @Componentpublic @interface Service {    ...}複製代碼
    • @Repository

      @Componentpublic @interface Repository {    ...}複製代碼
    • @Controller

      @Componentpublic @interface Controller {    ...}複製代碼
    • @Configuration

      @Componentpublic @interface Configuration {  ...}複製代碼

Spring 模式註解:Stereotype Annotations

Spring 註解驅動示例

註解驅動上下文 AnnotationConfigApplicationContext , Spring Framework 3.0 開始引入的

@Configurationpublic class SpringAnnotationDemo {​    public static void main(String[] args) {​        //   XML 配置文件驅動       ClassPathXmlApplicationContext        // Annotation 驅動        // 找 BeanDefinition        // @Bean @Configuration        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();        // 註冊一個 Configuration Class = SpringAnnotationDemo        context.register(SpringAnnotationDemo.class);        // 上下文啓動        context.refresh();​        System.out.println(context.getBean(SpringAnnotationDemo.class));​    }}複製代碼

@SpringBootApplication 標註當前一些功能

  • @SpringBootApplication

    • @SpringBootConfiguration

      • @Configuration

        • @Component

SpringApplication Spring Boot 應用的引導

基本寫法

SpringApplication springApplication = new SpringApplication(MicroservicesProjectApplication.class);        Map<String,Object> properties = new LinkedHashMap<>();        //隨機獲取端口號        properties.put("server.port",0);        springApplication.setDefaultProperties(properties);        springApplication.run(args);複製代碼

SpringApplicationBuilder

new SpringApplicationBuilder(MicroservicesProjectApplication.class) // Fluent API                // 單元測試是 PORT = RANDOM                .properties("server.port=0")  // 隨機向 OS 要可用端口                .run(args);複製代碼

Spring Boot 引導示例

@SpringBootApplicationpublic class MicroservicesProjectApplication {​    public static void main(String[] args) {        SpringApplication springApplication = new SpringApplication(MicroservicesProjectApplication.class);        Map<String,Object> properties = new LinkedHashMap<>();        properties.put("server.port",0);        springApplication.setDefaultProperties(properties);        ConfigurableApplicationContext context = springApplication.run(args);        // 有異常?        System.out.println(context.getBean(MicroservicesProjectApplication.class));    }}複製代碼

調整示例爲 非 Web 程序

@SpringBootApplicationpublic class MicroservicesProjectApplication {​    public static void main(String[] args) {        SpringApplication springApplication = new SpringApplication(MicroservicesProjectApplication.class);        Map<String, Object> properties = new LinkedHashMap<>();        properties.put("server.port", 0);        springApplication.setDefaultProperties(properties);        // 設置爲 非 web 應用        springApplication.setWebApplicationType(WebApplicationType.NONE);        ConfigurableApplicationContext context = springApplication.run(args);        // 有異常?        System.out.println(context.getBean(MicroservicesProjectApplication.class));        // 輸出當前 Spring Boot 應用的 ApplicationContext 的類名        System.out.println("當前 Spring 應用上下文的類:" + context.getClass().getName());    }}複製代碼

輸出結果:

當前 Spring 應用上下文的類:org.springframework.context.annotation.AnnotationConfigApplicationContext複製代碼

配置 Spring Boot 源

SpringAppliation 類型推斷

當不加以設置 Web 類型,那麼它採用推斷:

-> SpringAppliation() -> deduceWebApplicationType() 第一次推斷爲 WebApplicationType.SERVLET

  • WebApplicationType.NONE : 非 Web 類型

    • Servlet 不存在

    • Spring Web 應用上下文 ConfigurableWebApplicationContext 不存在

      • spring-boot-starter-web 不存在

      • spring-boot-starter-webflux 不存在

  • WebApplicationType.REACTIVE : Spring WebFlux

    • DispatcherHandler

      • spring-boot-starter-webflux 存在

    • Servlet 不存在

      • spring-boot-starter-web 不存在

  • WebApplicationType.SERVLET : Spring MVC

    • spring-boot-starter-web 存在

人工干預 Web 類型

設置 webApplicationType 屬性 爲 WebApplicationType.NONE

Spring Boot 事件

Spring 事件

Spring 內部發送事件

  • ContextRefreshedEvent

    • ApplicationContextEvent

      • ApplicationEvent

refresh() -> finishRefresh() -> publishEvent(new ContextRefreshedEvent(this));

  • ContextClosedEvent

    • ApplicationContextEvent

      • ApplicationEvent

close() -> doClose() -> publishEvent(new ContextClosedEvent(this));

自定義事件

PayloadApplicationEvent

Spring 事件 都是 ApplicationEvent 類型

發送 Spring 事件經過 ApplicationEventMulticaster#multicastEvent(ApplicationEvent, ResolvableType)

Spring 事件的類型 ApplicationEvent

Spring 事件監聽器 ApplicationListener

Spring 事件廣播器 ApplicationEventMulticaster

  • 實現類:SimpleApplicationEventMulticaster

Spring 事件理解爲消息

ApplicationEvent 至關於消息內容

ApplicationListener 至關於消息消費者、訂閱者

ApplicationEventMulticaster 至關於消息生產者、發佈者

Spring Boot 事件監聽示例

@EnableAutoConfigurationpublic class SpringBootEventDemo {​    public static void main(String[] args) {        new SpringApplicationBuilder(SpringBootEventDemo.class)                .listeners(event -> { // 增長監聽器                    System.err.println("監聽到事件 : " + event.getClass().getSimpleName());                })                .run(args)                .close();        ; // 運行    }}複製代碼

  1. ApplicationStartingEvent(1)

  2. ApplicationEnvironmentPreparedEvent(2)

  3. ApplicationPreparedEvent(3)

  4. ContextRefreshedEvent

  5. ServletWebServerInitializedEvent

  6. ApplicationStartedEvent(4)

  7. ApplicationReadyEvent(5)

  8. ContextClosedEvent

  9. ApplicationFailedEvent (特殊狀況)(6)

Spring Boot 事件監聽器

org.springframework.context.ApplicationListener=\org.springframework.boot.ClearCachesApplicationListener,\org.springframework.boot.builder.ParentContextCloserApplicationListener,\org.springframework.boot.context.FileEncodingApplicationListener,\org.springframework.boot.context.config.AnsiOutputApplicationListener,\org.springframework.boot.context.config.ConfigFileApplicationListener,\org.springframework.boot.context.config.DelegatingApplicationListener,\org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,\org.springframework.boot.context.logging.LoggingApplicationListener,\org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener複製代碼

ConfigFileApplicationListener 監聽 ApplicationEnvironmentPreparedEvent 事件

從而加載 application.properties 或者 application.yml 文件

Spring Boot 不少組件依賴於 Spring Boot 事件監聽器實現,本質是 Spring Framework 事件/監聽機制

SpringApplication 利用

  • Spring 應用上下文(ApplicationContext)生命週期控制 註解驅動 Bean

  • Spring 事件/監聽(ApplicationEventMulticaster)機制加載或者初始化組件

q1:webApplicationType分爲三種都有什麼實用地方

q2:框架底層的事件是單線程麼?業務實現是否能夠使用事件去實現?若是使用事件實現會不會是否是會有性能問題?

public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {​  @Nullable  private Executor taskExecutor;    ...}複製代碼
相關文章
相關標籤/搜索