SpringBoot对比SpringMVC最大的优点就是实现了约定大于配置
SpringMVC:通过<Bean>的方式来配置各种配置类
SpringBoot:通过@Configuration+@Bean的方式来配置配置类
问题:只不过是换了一种写法,怎么就约定大于配置了呢,Boot为什么就比MVC减少了配置呢
首先SpringBoot快速开发工具包,之所以能够便捷的开发
是因为它的自动装配+各个组件自己定义的Starter的机制
在SpringBoot中,各个成熟的组件要自己写一个默认的Starter(@Configuration+@Bean)比如Mybatis,这样一来组件已经定义了一套默认的配置类,只需要引用它的默认配置类,就可以配置了省去之前SpringMVC每次都要配置一遍。
①:自动装配
刚刚说了,每个组件都提供自己默认的配置类
配置类的本质就是一个SpringBean,只要是SpringBean就得交由Spring容器管理。
问题:IOC容器如何能将持有@Component的类进行加载并创建呢?
为什么不用@ComponentScan扫描?
可能有人会说@SpringBootApplication里的@ComponentScan不就可以扫描之后放到IOC容器中么。
Application.java的@ComponentScan默认是扫描同包下同级以及以下的路径下的@Component
(这也是为啥启动类要放在包的最外层的原因)
各个组件自己提供的Starter是个jar包,不可能会出现在和启动类在同包下,既然不可能,@ComponentScan自然也就扫不到配置类,也就不能由IOC容器管理。
问题:@ComponentScan的注解不可以指定jar路径扫描么?
估计大家互相抄袭的自动装配原理文章会以为@ComponentScan扫不到Jar的路径
//此时已经把starter里的spring.factories的全路径给删掉了
@ComponentScan("com.yuwenwen.*")
答案是错误的,@ComponentScan指定路径是可以的,那这不就能实现自动装配了么?
一个springboot工程需要很多的starter包,如果都配置了,又得把每一个starter包的全路径都指定上,这只能叫做装配,谈不上自动装配。
springBoot自动装配真正追求的是只要把依赖引进来,starter的配置类就自动加载到IOC容器里面
SpringBoot的SPI机制,就解决了自动装配的问题
@SpringBootApplication ↓ @EnableAutoConfiguration ↓ @Import({AutoConfigurationImportSelector.class}) ↓ AutoConfigurationImportSelector.java ↓ public String[] selectImports(AnnotationMetadata annotationMetadata) 方法中
返回的String[]就是META-INF包下的spring.factories里定义的自动配置类的全路径
例如:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.yuwenwen.cofig.Cofig
这样一来,只需要把starter的的依赖引进去,starter的配置Bean就会自动的加载到IOC容器里面了
个人理解:大家约定好的META-INF包下的spring.factories的配置定义好的配置类就是SpringBoot中的约定大于配置。
②:自定义Starter
已经成熟的组件人家都把Starter都写好了打上jar包。你引个依赖就完事了。
那么自己想定义一个Starter呢
1:建工程(遵守命名规则)
- Spring官方Starter通常命名为spring-boot-starter-{name}如:spring-boot-starter-web
- Spring官方建议非官方Starter命名应遵循{name}-spring-boot-starter的格式:如yuwenwen-spring-boot-starter。
2:引依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.1.13.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.2.13.RELEASE</version>
</plugin>
</plugins>
</build>
3:编写Configration类
@Configuration
public class AutoConfigration {
@Bean
@ConditionalOnMissingBean(YuWenWenConfigration.class)
public YuWenWenConfigration yuWenWenConfigration() {
YuWenWenConfigration yuWenWenConfigration = new YuWenWenConfigration();
yuWenWenConfigration.setAge("27");
yuWenWenConfigration.setJobYear("5");
yuWenWenConfigration.setName("yuwenwen");
return yuWenWenConfigration;
}
}
4:编写spring.factories(将配置类的全路径配置上)
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.config.AutoConfigration
5:打包maven install
6: 主工程把刚才打包好的Stater依赖引进来
<dependency>
<groupId>com.yu</groupId>
<artifactId>yuwenwen-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
测试一下:
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(CloudBiz1Application.class, args);
applicationContext.addApplicationListener(new MyApplicationListener());
YuWenWenConfigration cofig = (YuWenWenConfigration) applicationContext
.getBean("yuWenWenConfigration");
System.out.println(cofig.getName());
}
已经在spring容器里拿到配置类了
结论:spring.factories+自定义Starter,只需引依赖就可以实现开箱即用的自动装配原理。