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 Framework 3.1
@EnableAutoConfiguration
: 激活自动装配 @Enable
-> @Enable
开头的
@EnableWebMvc
@EnableTransactionManagement
@EnableAspectJAutoProxy
@EnableAsync
@SpringBootConfiguration
: 等价于 @Configuration
-> Configuration Class 注解
@Component
-> @ComponentScan
处理类 -> ConfigurationClassParser
扫描类 ->
ClassPathBeanDefinitionScanner
ClassPathScanningCandidateComponentProvider
protected void registerDefaultFilters() { this.includeFilters.add(new AnnotationTypeFilter(Component.class)); ... }复制代码
Dubbo @Service
-> 2.5.7 -> new AnnotationTypeFilter(Service.class);
@Component
@Service
@Componentpublic @interface Service { ...}复制代码
@Repository
@Componentpublic @interface Repository { ...}复制代码
@Controller
@Componentpublic @interface Controller { ...}复制代码
@Configuration
@Componentpublic @interface Configuration { ...}复制代码
注解驱动上下文 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);复制代码
new SpringApplicationBuilder(MicroservicesProjectApplication.class) // Fluent API // 单元测试是 PORT = RANDOM .properties("server.port=0") // 随机向 OS 要可用端口 .run(args);复制代码
@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)); }}复制代码
@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复制代码
当不加以设置 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
存在
设置 webApplicationType 属性 为 WebApplicationType.NONE
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
相当于消息生产者、发布者
@EnableAutoConfigurationpublic class SpringBootEventDemo { public static void main(String[] args) { new SpringApplicationBuilder(SpringBootEventDemo.class) .listeners(event -> { // 增加监听器 System.err.println("监听到事件 : " + event.getClass().getSimpleName()); }) .run(args) .close(); ; // 运行 }}复制代码
ApplicationStartingEvent(1)
ApplicationEnvironmentPreparedEvent(2)
ApplicationPreparedEvent(3)
ContextRefreshedEvent
ServletWebServerInitializedEvent
ApplicationStartedEvent(4)
ApplicationReadyEvent(5)
ContextClosedEvent
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; ...}复制代码