一个SpringBoot程序
系统要求
Java 8以上
Maven3.3以上
idea2019.1.2以上
maven设置
<mirrors>
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>jdk-1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
</profiles>
创建项目
创建一个普通的maven项目
引入依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
创建主程序类
package com.qin.boot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* 主程序类
* @SpringBootApplication这是一个Springboot应用
*/
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class,args);
}
}
创建Controller
package com.qin.boot.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
//@Controller
//@ResponseBody
@RestController
public class HelloController {
@RequestMapping("/hello")
public String handle01(){
return "Hello,Spring boot 2";
}
}
测试
运行主程序类的main方法
配置
在resources下创建 application.properties文件
所有的配置都可以在这个文件里修改
可参照spring官方文档:Common Application Properties (spring.io)
导入jar包简化部署
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
把项目打成jar包,可直接在命令提示符中部署项目
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uM4EpAm7-1624086895698)(C:\Users\qinjingzhuo\Desktop\MakeDown\SpringBoot\image\2.1.png)]
- 注意:需要取消命令提示符的快速编辑模式
SpringBoot特点
依赖管理
<!--父项目 springboot dependencies
声明了jar包的所有版本-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
修改依赖版本
查看springboot dependencies中的key
在pom文件中重写标签
<properties>
<mysql.version>5.1.47</mysql.version>
</properties>
starter场景启动器
-
spring-boot-starter.*
引入这个场景依赖,就会引入这个场景的所有依赖 -
springboot所支持的场景依赖
https://docs.spring.io/spring-boot/docs/current/reference/html/using.html#using.build-systems.starters -
也可以导入第三方场景依赖
-
所有场景依赖的最底层的依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>2.3.4.RELEASE</version> <scope>compile</scope> </dependency>
自动配置
- 自动配置Tomcat
- 引入Tomcat依赖
- 配置Tomcat
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.3.4.RELEASE</version>
<scope>compile</scope>
</dependency>
-
自动配置SpringMVC
-
引入SpringMVC所有组件
-
自动配置SpringMVC常用组件
@SpringBootApplication public class MainApplication { public static void main(String[] args) { //返回IOC容器 ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args); //查看IOC中的组件 String[] beanDefinitionNames = run.getBeanDefinitionNames(); for (String beanDefinitionName : beanDefinitionNames) { System.out.println(beanDefinitionName); } } }
-
-
自动扫描包文件
-
主程序所在的包以及其下面的所有包都可以被扫描到
-
无需配置包扫描
-
不可以在其以外的地方扫描
-
如果想要改变扫描路径
-
@SpringBootApplication(scanBasePackages = "com.qin")
-
@ComponentScan("com.qin")
-
-
-
各种配置都有默认值
- 默认配置最终都是映射到MultipartProperties
- 配置文件的值最终回绑定到每个类上,这个类会在容器中创建对象
-
按需加载所有的自动配置项
容器功能
组件添加
@Configuration 创建config类
@Bean添加组件
@Import添加组件
@Conditional 条件装配:满足Conditional指定的条件,则进行组件注入
@ImportResource 导入Spring的配置文件,让其进行生效
package com.qin.boot.config;
import com.qin.boot.bean.Cat;
import com.qin.boot.bean.User;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportResource;
/**
* 配置类里面使用@Bean标注在方法上给容器注册组件,默认是单实例的
* 配置类本身也是组件
* proxyBeanMethods 代理bean的方法
* 如果proxyBeanMethods等于true 代理对象调用方法,SpringBoot总会检查这个组件是否在容器中有
* 保持组件单实例
* Full(proxyBeanMethods=true) 每次都检查容器中是否存在bean,解决组建依赖
* Lite(proxyBeanMethods=false) 每次都直接创建一个新类,不需要检查,启动快
* 组件依赖:在容器中注册两个bean A,B 其中 A类中有B类对象. 在Full模式下,A中的B 和容器中的B是同一个
* 在Lite模式下 是新创建的B,不是容器中的B
* @Import({User.class})
* 给容器中自动创建出这个类型的组件
* @ConditionalOn***(name="")
* 条件判断,判断成功后,其下面的Bean才会被注册
* @ImportResource("classpath:***")
* 导入Spring的配置文件,让其进行生效
*/
@Import(User.class)
@Configuration(proxyBeanMethods = true)//告诉SpringBoot这是一个配置类 == 配置文件
@ConditionalOnMissingBean(name = "jack")//容器中没有id为jack的bean 才会注入下面的bean
@ImportResource("classpath:beans.xml")
public class MyConfig {
/**
* 外部不论对配置类的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象
* @return
*/
@Bean//给容器中添加组件,以方法名作为组件id,返回类型就是组件类型,返回的值,就是组件在容器中的实例
public User user(){
return new User(1,"盖伦");
}
@ConditionalOnBean(name = "user")//如果容器中有id为user的组件,才会注册下面的bean
@Bean
public Cat tom(){return new Cat(1,"tom");}
}
测试
package com.qin.boot;
import com.qin.boot.bean.Cat;
import com.qin.boot.bean.User;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.cache.CacheType;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
/**
* 主程序类
* @SpringBootApplication这是一个Springboot应用
*/
@ComponentScan("com.qin")
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
//返回IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
//查看IOC中的组件
/*String[] beanDefinitionNames = run.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
//从容器中获得组件
User user = run.getBean("user", User.class);
System.out.println(user);*/
//获取组件
String[] beanNamesForType = run.getBeanNamesForType(User.class);
for (String s : beanNamesForType) {
System.out.println(s);
//com.qin.boot.bean.User
//user
//@Import()注入成功
}
boolean tom = run.containsBean("tom");
System.out.println(tom);//true
//条件判断成功,注入 Bean -> tom
}
}
配置绑定
application.properties:
car.name=bm
car.price=10000
@ConfigurationProperties(prefix = “car”) 绑定 前缀为 car 的属性
- 直接在实体类中 注解 @Component 将bean注入到容器中
package com.qin.boot.bean;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 只有在容器中的组件,才可以进行配置绑定
*/
//@Component
@ConfigurationProperties(prefix = "car")
@Data
public class Car {
private String name;
private int price;
}
-
在配置类中 注解 @EnableConfigurationProperties(Car.class)
//开启Car配置绑定功能 //把这个Car注入到容器中 @Configuration @EnableConfigurationProperties(Car.class) public class MyConfig
自动配置原理
引导加载自动配置类
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication
@SpringBootConfiguration
@Configuration 代表当前是一个配置类
@ComponentScan
指定扫描那些
@EnableAutoConfiguration
@AutoConfigurationPackage//给容器中导入一个组件
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration
-
@AutoConfigurationPackage
自动导入包
@Import({Registrar.class})//给容器中带入一个组件 public @interface AutoConfigurationPackage //利用 Registrar给容器中导入一系列组件 //将MainApplication所在的包下的所有组件导入进来
-
@Import({AutoConfigurationImportSelector.class})
//利用这个方法给容器中批量导入组件 getAutoConfigurationEntry(AnnotationMetadata); //调用方法获取所有需要导入到容器中的配置类 List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes); //利用工厂加载得到所有组件 Map<String,List<String>>loadSpringFactorys(@Nullable ClassLoader classLoader); //默认扫描当前系统里面所有META-INF/spring.factories位置的文件
spring.factories文件里面写死了 springboot 一启动就要给容器中加载的所有配置类
按需开启
虽然127个场景的所有自动配置启动的时候会默认全部加载
但是按照条件装配规则最终会按需配置
自动装配流程:
雷丰阳2021版SpringBoot2零基础入门springboot全套完整版(spring boot2)_哔哩哔哩_bilibili
总结
- SpringBoot先加载所有的自动配置类 xxxAutoConfiguration
- 每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值 xxxProperties
- 生效的配置类会给容器中装配很多组件
- 只要容器中有这些组件,相当于这些功能就有了
- 只要用户有自己配置的,就优先使用用户的
- 定制化配置
- 用户直接自己@Bean替换底层的组件
- 用户直接修改properties文件的值
xxxAutoConfiguration—>组件—>xxxProperties里面拿值—>application.properties修改值
最佳实践
- 引入场景依赖
- 查看自动配置了哪些(debug=true)
- 是否需要修改
- 参照文档修改配置
- 自定义加入或者替换组件
- @Bean、@Component
- 自定义器
ps://www.bilibili.com/video/BV19K4y1L7MT?p=15)
总结
- SpringBoot先加载所有的自动配置类 xxxAutoConfiguration
- 每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值 xxxProperties
- 生效的配置类会给容器中装配很多组件
- 只要容器中有这些组件,相当于这些功能就有了
- 只要用户有自己配置的,就优先使用用户的
- 定制化配置
- 用户直接自己@Bean替换底层的组件
- 用户直接修改properties文件的值
xxxAutoConfiguration—>组件—>xxxProperties里面拿值—>application.properties修改值
最佳实践
- 引入场景依赖
- 查看自动配置了哪些(debug=true)
- 是否需要修改
- 参照文档修改配置
- 自定义加入或者替换组件
- @Bean、@Component
- 自定义器