SpringApplication是Spring Boot驱动应用上下文的引导类。git
1.Spring Boot项目的启动类有2种写法:github
写法一:web
写法2:spring
若是把写法2改为用写法1的方式,显示以下:ide
随机端口通常是单元测试用的。spring-boot
2.SpringApplication与SpringBootApplication的区别;单元测试
@SpringBootApplication 标注当前一些功能测试
SpringApplication :Spring Boot应用的引导spa
先看一下SpringBootApplication的注解:code
这个注解咱们重点关注3个地方,第一个:@ComponentScan,它是Spring Framework 3.1开始引入的,是扫描的做用。
第二个:@EnableAutoConfiguration,激活自动装配,@Enable模式,都是@Enable开头的,好比说:
@EnableWebMvc
@EnableTransactionManagement
@EnableAspectJAutoProxy
@EnableAsync
第三个:@SpringBootApplication
等价于@Configuration
->configuration class注解
说他等价的缘由在此:
举个例子(Spring注解驱动示例):
注解驱动上下文AnnotationConfigApplicationContext
:Spring Framework 3.0开始引入的
3.@Component的“派生性”
@Component
@Service
@Repository
@Controller
@Configuration
@Service、@Repository、@Controller、@Configuration里面都是@Component,这个叫作Spring的模式注解。
具体的依据能够去这儿看:https://github.com/spring-projects/spring-framework/wiki/Spring-Annotation-Programming-Model
元注解:标注元注解的注解。也就是说@Component是@Service、@Repository、@Controller、@Configuration的元注解,@Document是全部注解的元注解。
模式注解包括@Component,@Service,@Repository,@Controller,@RestController,@configuration等。(@Contrlloer、@Service、@Repository只是逻辑上的区分,对Spring而言,都是bean。物理上都是同样的,都是bean defination)
这个派生性只有在@Component里面生效。由于@Componnent和@ComponentScan的成队性,@ComponentScan去扫描@Component。它的“子”注解都会被扫进去。即凡是被@Component标注的都会被扫描进去。
为何@Component的会被扫描进去呢?
即处理类:ConfigurationClassParser
扫描类:
ClassPathBeanDefinitionScanner
ClassPathScanningCandidateComponentProvider
扫描以后用parse方法进行解析,
若是使用默认过滤器,Component、Repository、Service、Controller都会被扫进来。
继续这个方法往下跟:
这个方法的第一行,代表了只过滤component。
这就是为何他只扫描ComponentScan。
能够类比一下dubbo的@Service
->2.5.7版本->new AnnotationTypeFilter(Service.class);
@SpringBootApplication等同于@SpringBootConfiguration,等同于@Configuration,等同于@Component,因此他是一个bean,可是因为注解是不能继承的,因此叫“派生性”。
所谓@Component的“派生性”等同于注解的“继承”。
知道了什么是Spring模式注解和@Component的“派生性”以后,再回到注解驱动的例子:
先看SpringBoot的启动示例:
再看下String的:
对比能够看出输出的结果是同样的。因此其实,Spring Boot是驱动Spring的一个容器,只不过是谁来驱动的问题。
为了进一步证实这个观点,把上面的例子调整为非web程序:
打印出来的当前Spring应用上下文的类正是等于它:
现象出来以后,咱们看一下这个的本质:
WebApplicationType.NONE
:非web类型
Servlet
不存在
Spring Web应用上下文ConfigurableWebApplicationContext
不存在
spring-boot-starter-web
不存在
spring-boot-starter-webflux
不存在
WebApplicationType.REACTIVE
:Spring WebFlux
DespatcherHandler
spring-boot-starter-webflux
存在
Servlet
不存在
spring-boot-starter-web
不存在
WebApplicationType.SERVLET
:Spring MVC
spring-boot-starter-web
存在
若是2个包都加入,代码是有优先级的,判断以后,会选择Spring MVC
当不加以设置web类型时,它采用推断:
SpringApplication()
->deduceWebApplicationType()
第一次推断为WebApplicationType.SERVLET
,
设置webApplicationType属性为WebApplicationType.NONE
,
当设置为非web类型,他的server容器也不会启动了,程序就挂掉了。说明web类型会影响上下文。
设置以后,看看那个方法读调用了他:
因此说Spring Boot只是一层壳,核心仍是Spring Framework。
SpringApplication是Spring Boot驱动应用上下文的引导类。调用run方法的时候,
看到这,再回到一开始spring的那个例子:
和这个例子中的refresh()对应的。因此说,SpringApplication是Spring Boot驱动应用上下文的引导类。
最后看一下官方文档关于SpringApplicaiton的说明: