SpringApplication是Spring Boot驱动应用上下文的引导类。
1.Spring Boot项目的启动类有2种写法:
写法一:
写法2:
如果把写法2改成用写法1的方式,显示如下:
随机端口一般是单元测试用的。
2.SpringApplication与SpringBootApplication的区别;
@SpringBootApplication 标注当前一些功能
SpringApplication :Spring Boot应用的引导
先看一下SpringBootApplication的注解:
这个注解我们重点关注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
Spring的模式注解:Srereotype Annotations
元注解:标注元注解的注解。也就是说@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的说明: