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);//运行 } }
- ApplicationStartingEvent
- ApplicationEnvironmentPreparedEvent
- ApplicationContextInitializedEvent
- ApplicationPreparedEvent
- ContextRefreshedEvent
- ServletWebServerInitializedEvent
- ApplicationStartedEvent
- ApplicationReadyEvent
- ContextClosedEvent
- 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)机制加载或者初始化组件