大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺
SpringBoot框架详解
1. SpringBoot概述
1.1 springboot简介
springboot之所以能使用广泛也基于微服务分布式的的崛起。
1.2 SpringBoot特点
1.SpringBoot优点
• Create stand-alone Spring applications
• 创建独立Spring应用
• Embed Tomcat, Jetty or Undertow directly (no need to deploy WAR files)
• 内嵌web服务器
• Provide opinionated ‘starter’ dependencies to simplify your build configuration
• 自动starter依赖,简化构建配置
• Automatically configure Spring and 3rd party libraries whenever possible
• 自动配置Spring以及第三方功能
• Provide production-ready features such as metrics, health checks, and externalized configuration
• 提供生产级别的监控、健康检查及外部化配置
• Absolutely no code generation and no requirement for XML configuration
• 无代码生成、无需编写XML
SpringBoot是整合Spring技术栈的一站式框架
SpringBoot是简化Spring技术栈的快速开发脚手架
2.SpringBoot缺点
• 人称版本帝,迭代快,需要时刻关注变化
• 封装太深,内部原理复杂,不容易精通
1.3 Spring官网说明
官网文档架构查看版本新特性;
https://github.com/spring-projects/spring-boot/wiki#release-notes
2. SpringBoot案例
入门案例参照官方文档:https://docs.spring.io/spring-boot/docs/current/reference/html/index.html
上文官网文档架构中的入门对应连接Getting Started。
2.1 系统要求
2.2 创建项目
2.3 引入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>myproject</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.1</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
2.4 创建测试
import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*;
import org.springframework.web.bind.annotation.*;
@RestController
@EnableAutoConfiguration
public class Example {
@RequestMapping("/")
String home() {
return "Hello World!";
}
public static void main(String[] args) {
SpringApplication.run(Example.class, args);
}
}
2.5 测试验证
访问浏览器地址:http://localhost:8080/
返回:hello world!
3. SpringBoot特点
3.1 依赖管理
- 父项目做依赖管理
依赖管理
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
他的父项目
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
几乎声明了所有开发中常用的依赖的版本号,自动版本仲裁机制
3.2 场景启动器
1、见到很多 spring-boot-starter-* : *就某种场景
2、只要引入starter,这个场景的所有常规需要的依赖我们都自动引入
3、SpringBoot所有支持的场景
https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter
4、见到的 *-spring-boot-starter: 第三方为我们提供的简化开发的场景启动器。
5、所有场景启动器最底层的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.3.4.RELEASE</version>
<scope>compile</scope>
</dependency>
3.3 自动版本仲裁
无需关注版本号,自动版本仲裁
1、引入依赖默认都可以不写版本
2、引入非版本仲裁的jar,要写版本号。
3.可以修改默认版本号。
1、查看spring-boot-dependencies里面规定当前依赖的版本 用的 key。
2、在当前项目里面重写配置
<properties>
<mysql.version>5.1.43</mysql.version>
</properties>
4.自动配置
• 自动配好Tomcat
• 自动配好SpringMVC
• 引入SpringMVC全套组件
• 自动配好SpringMVC常用组件(功能)
• 自动配好Web常见功能,如:字符编码问题
• SpringBoot帮我们配置好了所有web开发的常见场景
• 默认的包结构
• 主程序所在包及其下面的所有子包里面的组件都会被默认扫描进来
• 无需以前的包扫描配置
• 想要改变扫描路径,@SpringBootApplication(scanBasePackages="com")
• 或者@ComponentScan 指定扫描路径
@SpringBootApplication
等同于
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.atguigu.boot")
• 各种配置拥有默认值
• 默认配置最终都是映射到某个类上,如:MultipartProperties
• 配置文件的值最终会绑定每个类上,这个类会在容器中创建对象
• 按需加载所有自动配置项
• 非常多的starter
• 引入了哪些场景这个场景的自动配置才会开启
• SpringBoot所有的自动配置功能都在 spring-boot-autoconfigure 包里面
。。。
4. SpringBoot容器功能
2.1、组件添加
1、@Configuration
@Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件
1、配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的
2、配置类本身也是组件
3、proxyBeanMethods:代理bean的方法
Full(proxyBeanMethods = true)、【保证每个@Bean方法被调用多少次返回的组件都是单实例的】
Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】
组件依赖必须使用Full模式默认。其他默认是否Lite模式
2、@Bean、@Component、@Controller、@Service、@Repository
定义一些组件
3、@ComponentScan、@Import
@ComponentScan("com.hey.boot")
指定包扫描路径
@Import({User.class, DBHelper.class})
给容器中自动创建出这两个类型的组件、默认组件的名字就是全类名
4、@Conditional
条件装配:满足Conditional指定的条件,则进行组件注入
2.2、原生配置文件引入
1、@ImportResource
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<bean id="haha" class="com.atguigu.boot.bean.User">
<property name="name" value="zhangsan"></property>
<property name="age" value="18"></property>
</bean>
<bean id="hehe" class="com.atguigu.boot.bean.Pet">
<property name="name" value="tomcat"></property>
</bean>
</beans>
// xml配置bean以后,通过注解@ImportResource("classpath:beans.xml")放到容器中。
@ImportResource("classpath:beans.xml")
public class MyConfig {
public static void main(String[] args) {
//1、返回我们IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
boolean haha = run.containsBean("haha");
boolean hehe = run.containsBean("hehe");
System.out.println("haha:"+haha);//true
System.out.println("hehe:"+hehe);//true
}
}
2.3、配置绑定
1、@ConfigurationProperties
/** * 只有在容器中的组件,才会拥有SpringBoot提供的强大功能 */
@Component
@ConfigurationProperties(prefix = "mycar")
public class Car {
}
2、@EnableConfigurationProperties + @ConfigurationProperties
3、@Component + @ConfigurationProperties
@EnableConfigurationProperties(Car.class)
//1、开启Car配置绑定功能
//2、把这个Car这个组件自动注册到容器中
public class MyConfig {
}
5. SpringBoot配置原理
5.1 自动配置流程
首先是主启动类注解@SpringBootApplication,这是一个组合注解,其中有两个比较重要的注解@SpringBootConfiguration
@EnableAutoConfiguration
@SpringBootConfiguration注解是一个配置注解@Configuration,其本质也是一个spring组件@Component。
@EnableAutoConfiguration注解有两个比较重要的注解:
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
@AutoConfigurationPackage注解下有一个注解@Import(AutoConfigurationPackages.Registrar.class),springboot注册器,Registrar注册器通过registerBeanDefinitions方法获取包扫描路径。
springboot选择器AutoConfigurationImportSelector.class是springboot自动配置的核心类。AutoConfigurationImportSelector类通过getAutoConfigurationEntry方法中getCandidateConfigurations方法获取META-INF/spring.factories中已经配置好的xxxAutoConfiguration配置,根据@ConditionalOnMissingBean与@ConditionalOn判断加载指定的配置,判断条件一般指jar包是否引入,而不是全部加载spring.properties中的配置。
5.2 自动配置源码分析
主启动类注解
@SpringBootApplication
public class UnitTestApplication {
public static void main(String[] args) {
SpringApplication.run( UnitTestApplication.class, args );
}
}
引导加载自动配置类
@SpringBootConfiguration
@EnableAutoConfiguration
public @interface SpringBootApplication {
}
@SpringBootConfiguration
本质是一个@Configuration。代表当前是一个配置类,本质是@Component,是spring组件。
@Configuration
public @interface SpringBootConfiguration {
}
@Component
public @interface Configuration {
}
@EnableAutoConfiguration
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}
@AutoConfigurationPackage
springBoot注册器Registrar,获取扫描路径。
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
}
@Import(AutoConfigurationImportSelector.class)
自动配置选择器,选择注入配置的信息
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 获取配置信息
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
// 返回字符串数组
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 这里获取配置信息
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
// 去除过滤掉的组件
configurations.removeAll(exclusions);
configurations = getConfigurationClassFilter().filter(configurations);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
// 加载配置信息
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
// 具体加载方法
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
ClassLoader classLoaderToUse = classLoader;
if (classLoaderToUse == null) {
classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
}
String factoryTypeName = factoryType.getName();
return loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
}
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
Map<String, List<String>> result = cache.get(classLoader);
if (result != null) {
return result;
}
result = new HashMap<>();
try {
// 具体加载路径FACTORIES_RESOURCE_LOCATION:
// public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<?, ?> entry : properties.entrySet()) {
String factoryTypeName = ((String) entry.getKey()).trim();
String[] factoryImplementationNames =
StringUtils.commaDelimitedListToStringArray((String) entry.getValue());
for (String factoryImplementationName : factoryImplementationNames) {
result.computeIfAbsent(factoryTypeName, key -> new ArrayList<>())
.add(factoryImplementationName.trim());
}
}
}
// Replace all lists with unmodifiable lists containing unique elements
result.replaceAll((factoryType, implementations) -> implementations.stream().distinct()
.collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList)));
cache.put(classLoader, result);
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load factories from location [" +
FACTORIES_RESOURCE_LOCATION + "]", ex);
}
return result;
}
虽然我们127个场景的所有自动配置启动的时候默认全部加载。xxxxAutoConfiguration
按照条件装配规则(@Conditional),最终会按需配置。
3.3、修改默认配置
```java
@Bean
@ConditionalOnBean(MultipartResolver.class) //容器中有这个类型组件
@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) //容器中没有这个名字 multipartResolver 的组件
public MultipartResolver multipartResolver(MultipartResolver resolver) {
//给@Bean标注的方法传入了对象参数,这个参数的值就会从容器中找。
//SpringMVC multipartResolver。防止有些用户配置的文件上传解析器不符合规范
// Detect if the user has created a MultipartResolver but named it incorrectly
return resolver;
}
给容器中加入了文件上传解析器;
总结:
• SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration
• 每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件进行了绑定
• 生效的配置类就会给容器中装配很多组件
• 只要容器中有这些组件,相当于这些功能就有了
• 定制化配置
• 用户直接自己@Bean替换底层的组件
• 用户去看这个组件是获取的配置文件什么值就去修改。
xxxxxAutoConfiguration ---> 组件 ---> xxxxProperties里面拿值 ----> application.properties
3.4、最佳实践
• 引入场景依赖
• https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter
• 查看自动配置了哪些(选做)
• 自己分析,引入场景对应的自动配置一般都生效了
• 配置文件中debug=true开启自动配置报告。Negative(不生效)\Positive(生效)
• 是否需要修改
• 参照文档修改配置项
• https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#common-application-properties
• 自己分析。xxxxProperties绑定了配置文件的哪些。
• 自定义加入或者替换组件
• @Bean、@Component。。。
• 自定义器 XXXXXCustomizer;
• ......
5.3 开发技巧
4.1、Lombok
1、引入依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
2、idea中搜索安装lombok插件
3、常用注解
@NoArgsConstructor
@AllArgsConstructor
@Data
@ToString
@EqualsAndHashCode
@Slf4j
4.2、dev-tools
这是一个假的热部署,项目或者页面修改以后:Ctrl+F9;
真正的热部署使用插件rebel。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
4.3、Spring Initailizr(项目初始化向导)
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/171533.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...