SpringApplication认识

SpringApplication

SpringApplication Spring Boot 驱动Spring应用上下文的引导类

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
    .........  
}
@ComponentScan是Spring FrameWork3.1版本开始引入的
@EnableAutoConfiguration:激活自动装配     @Enable->@Enable开头的(Enable开头的取个名字叫激活模式)
  •  @EnableWebMvc
  •  @EnableTransactionManagement
  •  @EnableAspectJAutoProxy
  •  @EnableAsync
@SpringBootConfiguration:等价于@Configguration ->Configuration Class 注解

@Component的"派生性"

(阅读Spring注解编程模型:https://github.com/spring-projects/spring-framework/wiki/Spring-Annotation-Programming-Model
@Component就是下面@Service以及其他的元注解(Meta-Annotations)

@Component->@ComponentScan
处理类 -> ConfigurationClassParser

扫描类 -> ClassPathBeanDefinitionScanner
        ClassPathBeanDefinitionScanner
ClassPathScanningCandidateComponentProvider
    protected void registerDefaultFilters() {
        this.includeFilters.add(new AnnotationTypeFilter(Component.class));
           ........
    }

所以我们扫描到的都是Component注解的,也就是下面几个

 
  • @Service

 

@Component
public @interface Service{
    ........
}

 

  • @Controller

 

@Component
public @interface Controller{
    ........
}

 

  • @Repository

 

@Component
public @interface Repository{
    ........
}

 

  • @Configuration

 

@Component
public @interface Configuration{
    ........
}

 Spring模式注解:Stereotype Annotations(在 Spring 中任何标注 @Component 的组件都可以成为扫描的候选对象这就是模式注解)

 

 Spring注解驱动示例

注解驱动上下文 AnnotionConfigApplicationContext,Spring FrameWork 3.0 开始导入

@Configuration
public class SpringAnnotationDemo {

    public static void main(String[] args) {
        // XML配置文件驱动    ClassPathXmlApplicationContext
        //Annotation驱动       (两者都是找BeanDefinition)
        AnnotationConfigApplicationContext  context = new AnnotationConfigApplicationContext();
        //注册一个Configuration class = SpringAnnotationDemo
        context.register(SpringAnnotationDemo.class);
        //上下文启动
        context.refresh();
        System.out.println(context.getBean(SpringAnnotationDemo.class));
    }
}

 

 

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
@SpringBootApplication标注当前一些功能
@SpringBootApplication
@SpringBootConfiguration
@Configuration
@Component
上面就是@SpringBootApplication逐步等同于@Component,也进一步反映了下面所说的@Component的派生性,最终归宿还是Bean
    public static void main(String[] args) {
        new SpringApplicationBuilder(Application.class)
                .properties("server.port=0")  //0的意思是随机向操作系统要可用端口
                .run(args);
    }

Spring Boot引导示例

public static void main(String[] args) {
        SpringApplication springApplication = new SpringApplication(Application.class);
        Map<String,Object> proprities = new LinkedHashMap<>();
        proprities.put("server.port","0");
        springApplication.setDefaultProperties(proprities);

   ConfigurableApplicationContext context = springApplication.run(args);
     System.out.println(context.getBean(Application.class));
}

 

 调整示例为非web程序

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication springApplication = new SpringApplication(Application.class);
        Map<String,Object> proprities = new LinkedHashMap<>();
        proprities.put("server.port","0");
        springApplication.setDefaultProperties(proprities);
        //设置为非web应用
        springApplication.setWebApplicationType(WebApplicationType.NONE);
        ConfigurableApplicationContext context = springApplication.run(args);
        System.out.println(context.getBean(Application.class));
        //输出当前Spring Boot应用的ApplicationContext的类名
        System.out.println("当前Spring应用的上下文的类:"+context.getClass().getName());
    }

}

输出:当前Spring应用的上下文的类:org.springframework.context.annotation.AnnotationConfigApplicationContext(这个就是我们前面写的SpringAnnotationDemo里面的context)

 

配置SpringBoot源

 

SpringApplication类型推断

当不加以设置Web类型,那么它采用推断

->SpringApplication() -> dedeuceWebApplicationType()第一次推断为WebApplicationType.SERVLET(Spring boot 2.0.3版本,在2.2.1版本deduceEnvironmentClass推断为WebApplicationType.NONE)

 

WebApplicationType.REACTIVE:Spring WebFlux
    DispatcherHandler
    spring-boot-starter-webflux 存在
WebApplicationType.SERVLET:Spring MVV
    Spring-boot-starter-web 存在
WebApplicationType.NONE:非Web类型
    Servlet 不存在
    Spring Web上下文 ConfigurableWebApplicationContext 不存在
      spring-boot-starter-web 不存在(这个地方就是pom文件里的)
      spring-boot-starter-webflux 不存在
(根据下面的存在与否SpringApplication就能知道是什么环境[环境一说是在2.2.1版本:StandardEnvironment])

人工干预Web类型

设置webApplicationType熟悉为WebApplicationType.NONE

 

 

Spring Boot 事件

public class SpringEventListenerDemo {

    public static void main(String[] args) {
        GenericApplicationContext context = new GenericApplicationContext();
        //添加事件监听器
//        context.addApplicationListener(new ApplicationListener<ApplicationEvent>() {
//            @Override
//            public void onApplicationEvent(ApplicationEvent event) {
//                System.err.println("监听事件:"+event);
//            }
//        });

        //添加自定义监听器
        context.addApplicationListener(new ClosedListener());

        //启动spring应用上下文
        context.refresh();

        //两个事件,一个是ContextRefreshedEvent,一个是PayloadApplicationEvent
        //Spring应用上下文发布时间
        context.publishEvent("HelloWorld");//发布一个HelloWorld内容的事件
        //一个是我自己的是事件
        context.publishEvent(new MyEvent("HelloWorld 2019"));

        //关闭应用上下文
        context.close();
    }

    private static class ClosedListener implements ApplicationListener<ContextClosedEvent>{

        @Override
        public void onApplicationEvent(ContextClosedEvent event) {
            System.out.println("关闭上下文时间"+event);
        }
    }

    private static class MyEvent extends ApplicationEvent{


        public MyEvent(Object source) {
            super(source);
        }
    }

}

 

Spring事件

ContextRefreshedEvent
  ApplicationContextEvent
    ApplicationEvent
refresh()->finishRefresh() ->publishEvent(new ContextRefreshedEvent(this))
ContextClosedEvent

  ApplicationContextEvent
    ApplicationEvent
refresh()->finishRefresh() ->publishEvent(new ContextRefreshedEvent(this))


自定义事件

PayloadApplicationEvent

 

Spring事件都是ApplicationEvent类型

 

发送Spring事件通过ApplicationEventMulticaster#multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType)

 

Spring事件的类型 ApplicationEvent

 

Spring事件监听器 ApplicationListener

 

Spring事件广播器ApplicationEventMulticaster

 

Spring事件理解为消息

  ApplicationEvent相当于消息内容  

  ApplicationListener 相当于消息消费者,订阅者

  ApplicationEventMulticaster 相当于消息生产者,发布者

 

Spring Boot事件监听示例

@EnableAutoConfiguration
public class SpringBootEventDemo {
    public static void main(String[] args) {
        new SpringApplicationBuilder(SpringBootEventDemo.class)
                .listeners(event -> {
                    System.out.println("监听到事件:" + event.getClass().getName());
                })//增加监听器
                .run(args);//运行
    }
}
  1. ApplicationStartingEvent
  2. ApplicationEnvironmentPreparedEvent
  3. ApplicationContextInitializedEvent
  4. ApplicationPreparedEvent
  5. ContextRefreshedEvent
  6. ServletWebServerInitializedEvent
  7. ApplicationStartedEvent
  8. ApplicationReadyEvent
  9. ContextClosedEvent
  10. ApplicationFailedEvent(特殊情况)

SpringBoot事件监听器
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)机制加载或者初始化组件

上一篇:springboot学习笔记(二)—— springboot的启动模式设置


下一篇:SpringBoot 2.x中为tomcat配置ssl(https)支持