大家好,我是超级苦力怕,这篇文章记录黑马 SpringBoot3+Vue3 课程的基础篇,主要讲解了 SpringBoot 的相关知识,通过此篇文章,将带你整合 MyBatis、玩转 Bean 管理、再把自动配置和 starter 拆开给你看。打牢底盘,下一篇实战直接上Redis、JWT、Vue3,全栈流程一把梭。
SpringBoot是Spring框架提供的一个子项目,用于快速构建Spring应用程序
特性(优点): 起步依赖、自动配置等
本质上是一个Maven坐标,整合了完成一个功能需要的所有坐标
在
pom.xml中,对应的starter依赖,内部继承了一个父工程(spring-boot-starter-parent),定义了各个技术软件依赖的版本,因此大部分坐标无需手动配置。

遵循约定大于配置的原则,在boot程序启动后,一些bean对象会自动注入到IoC容器,不需要手动声明,简化开发。
以Mybatis为例,下图是Spring对应的依赖,在Spring中,我们还需要单独配置
SqlSessionFactoryBean和MapperScannerConfigurer,但如果是SpringBoot,无需配置。

其他特性如下:
1.创建Maven工程
2.导入spring-boot-starter-web起步依赖(勾选Spring Web即可)

3.编写Controller
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello(){
return "hello";
}
}4.提供启动类
@SpringBootApplication
public class SpringBoot4Application {
public static void main(String[] args) {
SpringApplication.run(SpringBoot4Application.class, args);
}
}5.输入localhost:端口号/hello即可看到结果

创建过程
1.Maven工程配置(Archetype选择quickstart即可),接着确认。

2.导入pom依赖
起步依赖父工程:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.6</version>
</parent>引入web起步依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>3.提供启动类
将原先启动类App改为SpringBootCreateApplication ,加入注解,修改内部方法。
注:这里名字默认为自己项目的名字+Application,不能为SpringBootApplication,会影响注解。
@SpringBootApplication
public class SpringBootCreateApplication{
public static void main( String[] args ){
SpringApplication.run(SpringBootCreateApplication.class,args);
}
}4.添加resources和application.properties

到这里,Maven工程已经改为了SpringBoot初始工程了。
在SpringBoot中,配置文件主要分为properties与yaml两种
官方网址拥有对应的属性书写格式(在SpringBoot中可以快速提示)
<官方网址传送门>

使用示例:
#改端口号
server.port=9090
#改初始路径
server.servlet.context-path=/start以快速入门的案例,我们的访问地址改为了localhost:9090/start/hello

yml配置信息主要为三方技术配置信息和自定义配置信息,这里主要讲自定义配置信息,使用到了@Value和@ConfigurationProperties两个注解。
以properties配置文件的配置作为示例
server:
port: 9090
servlet:
context-path: /start书写有以下特征
获取方法:使用@Value("${键名}")
样板示例
email:
user: 593140521@qq.com
code: jfejwezhcrzcbbbb
host: smtp.qq.com
auth: true使用示例
@Component
public class EmailProperties{
@Value("${email.user}")
//发件人邮箱
public String user;
@Value("${email.code}")
//授权码
public String code;
@Value("${email.host}")
//发件人邮箱对应应用服务
public String host;
@Value("${email.auth}")
//是否需要对发件人信息做验证
private boolean auth;
}简化方法:使用@ConfigurationProperties(prefix="前缀")。
由于email下有共同子层级,因此可以使用该注解
@ConfigurationProperties(prefix = "email")
@Component
public class EmailProperties{
//发件人邮箱
public String user;
//授权码
public String code;
//发件人邮箱对应应用服务
public String host;
//是否需要对发件人信息做验证
private boolean auth;
}使用前提 1.前缀需要和配置文件的前缀名一致 2.实体类的成员变量名与配置文件的键名一致
在原先的Spring中,我们需要进行导入依赖,并配置Bean对象,如SqlSessionFactoryBean、MapperScannerConfigurer、DataSource

在SpringBoot中,我们仅需要导入Mybatis对应的起步依赖,并在yml文件中输入配置信息即可,随后便可以正常书写Controller、Service与Mapper层。

1.创建SpringBoot,并勾选Mybatis,MySQL,Web开发对应起步依赖,创建即可

2.准备数据库(user)

3.创建application.yml,并进行配置
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mybatis
username: root
password: 1234564.创建对应的Controller、Service、Mapper层并启动
Controller:
@RestController
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/findById")
public User findById(Integer id){
return userService.findById(id);
}
}Service:
public interface UserService {
public User findById(Integer id);
}
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public User findById(Integer id) {
return userMapper.findById(id);
}
}Mapper:
@Mapper
public interface UserMapper {
@Select("select * from user where id = #{id}")
public User findById(Integer id);
}启动测试

Bean扫描有多种方式,如XML文件,如配置类,那么SpringBoot是怎么进行Bean扫描的呢?
1.XML文件:
<context:component-scan base-package="com.coolipa"/>2.配置类:
@ComponentScan(basePackages="com.coolipa")在SpringBoot的启动类中,有@SpringBootApplication注解,他由三个注解组合而来
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
public class SpringBoot8Application {
public static void main(String[] args) {
SpringApplication.run(SpringBoot8Application.class, args);
}
}由于涵盖了@ComponentScan注解,且没有指定扫描路径,因此默认涵盖启动类所在的包及其子包。
因此,如果有扫描不到的地方,可以手动添加@ComponentScan并覆盖路径
如果要注册的bean对象来自于第三方(不是自定义),是无法使用@Component 及衍生注解声明bean的。
因此,SpringBoot提供了@Bean与@Import两个注解解决这个问题
如果想要注册Bean,我们只需要在启动类中定义方法,并用@Bean注解,将方法返回值交给IOC容器管理,成为IOC容器的bean对象。
同时通过修改启动类,查看是否正常获取bean。
@SpringBootApplication
public class SpringBoot9Application {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(SpringBoot9Application.class, args);
DruidDataSource dds = ctx.getBean(DruidDataSource.class);
System.out.println(dds);
}
@Bean
public DruidDataSource druidDataSource(){
return new DruidDataSource();
}
}运行结果:正常获取
{
CreateTime:"2025-11-25 12:33:05",
ActiveCount:0,
PoolingCount:0,
CreateCount:0,
DestroyCount:0,
CloseCount:0,
ConnectCount:0,
Connections:[
]
}由于启动类更多是用来启动,所以不推荐在启动类中更改。
改进方案:在配置类中集中注册即可
@Configuration
public class DruidConfig {
//如果方法内部需要用到IOC容器中已有bean对象,只需要在方法上声明即可
@Bean
public DruidDataSource druidDataSource(){
return new DruidDataSource();
}
}只需要在启动类上使用@Import(Xxx.class)即可,可以导入任何类,通常导入配置类、ImportSelector接口实现类。
导入配置类:
这里已经将启动类放在启动类所在包之外。
@SpringBootApplication
@Import(DruidConfig.class)
public class SpringBoot9Application {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(SpringBoot9Application.class, args);
DruidDataSource dds = ctx.getBean(DruidDataSource.class);
System.out.println(dds);
}
}运行结果
{
CreateTime:"2025-11-25 13:08:32",
ActiveCount:0,
PoolingCount:0,
CreateCount:0,
DestroyCount:0,
CloseCount:0,
ConnectCount:0,
Connections:[
]
}Import可以直接使用数组{导入1,导入2},但并不美观,不常用
导入ImportSelector接口实现类
创建接口实现类,实现ImportSelector接口,返回对应数组(全类名)即可。
public class DruidImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.coolipa.config.DruidConfig"};
}
}此时在启动类,只需要导入该接口即可
@SpringBootApplication
@Import(DruidImportSelector.class)
public class SpringBoot9Application {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(SpringBoot9Application.class, args);
DruidDataSource dds = ctx.getBean(DruidDataSource.class);
System.out.println(dds);
}
}运行结果:
{
CreateTime:"2025-11-25 13:08:32",
ActiveCount:0,
PoolingCount:0,
CreateCount:0,
DestroyCount:0,
CloseCount:0,
ConnectCount:0,
Connections:[
]
}改进方案
在实际开发中,更多的是写入配置文件,通过类加载器读取文件(通过一个流)
配置文件(druid.imports)
com.coolipa.config.DruidConfig接口实现类
public class DruidImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
List<String> imports = new ArrayList<>();
InputStream is = DruidImportSelector.class.getClassLoader().getResourceAsStream("druid.imports");
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line = null;
try {
while ((line = br.readLine())!=null){
imports.add(line);
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (br!=null){
try {
br.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
return imports.toArray(new String[0]);
}
}建立一个Annotation注解,配置如下

//添加元注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import(DruidImportSelector.class)
public @interface EnableDruidConfig {
}此时修改启动类注解
@SpringBootApplication
@EnableDruidConfig
public class SpringBoot9Application {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(SpringBoot9Application.class, args);
DruidDataSource dds = ctx.getBean(DruidDataSource.class);
System.out.println(dds);
}
}运行结果仍旧一样,不再显示
我们学会了如何注册Bean,还得往里面赋值,这时候有着很多方法
1.通过new对象的时候,赋值再注入
@Bean
public DruidDataSource druidDataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setUsername("root");
druidDataSource.setPassword("123456");
druidDataSource.setUrl("jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC");
druidDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
return druidDataSource;
}缺点:需要修改java代码,需要重新编译打包,较麻烦。
2.通过放在配置文件,并通过@Value注入
properties文件
# 数据库基础配置
spring.datasource.url=jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver配置类
@Bean
public DruidDataSource druidDataSource(@Value("${spring.datasource.username}") String name,@Value("${spring.datasource.password}")String password,@Value("${spring.datasource.url}") String url,@Value("${spring.datasource.driver-class-name}") String driver ){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setUsername(name);
druidDataSource.setPassword(password);
druidDataSource.setUrl(url);
druidDataSource.setDriverClassName(driver);
return druidDataSource;
}缺点:如果配置文件没有配置,则报错,从而导致运行中断
改进方案:使用@Conditional的衍生注解,常用注解如下
这里会在自定义starter和在SpringBoot源码中常见
注解 | 说明 |
|---|---|
@ConditionalOnProperty | 配置文件中存在对应的属性,才声明该 bean |
@ConditionalOnMissingBean | 当不存在当前类型的 bean 时,才声明该 bean |
@ConditionalOnClass | 当前环境存在指定的这个类时,才声明该 bean |
@ConditionalOnProperty:配置文件中存在对应的属性,才声明该 bean
prefix:前缀 name:键名
@ConditionalOnProperty(prefix = "spring.datasource",name = {"username","driver-class-name","url","password"})
@Bean
public DruidDataSource druidDataSource(@Value("${spring.datasource.username}") String username,
@Value("${spring.datasource.password}")String password,
@Value("${spring.datasource.url}") String url,
@Value("${spring.datasource.driver-class-name}") String driver ){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setUsername(username);
druidDataSource.setPassword(password);
druidDataSource.setUrl(url);
druidDataSource.setDriverClassName(driver);
return druidDataSource;
}当配置文件注释其中一条之后,会报错No qualifying bean of type 'com.alibaba.druid.pool.DruidDataSource' available,即找不到bean。
@ConditionalOnMissingBean:当不存在当前类型的 bean 时,才声明该 bean
括号里是(DruidDataSource.class),即如果没有当前bean创建才执行
在配置类中新增加一个方法
@ConditionalOnMissingBean(DruidDataSource.class)
@Bean
public DruidDataSource druidDataSource1() {
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setUsername("root");
druidDataSource.setPassword("123456");
druidDataSource.setUrl("jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC");
druidDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
System.out.println("=== 创建自定义数据源(druidDataSource) ===");
System.out.println("运行正常");
return druidDataSource;
}此时我再将配置类里的内容注释掉,使bean无法正常进入IOC容器,运行看到提示信息。
=== 创建自定义数据源(druidDataSource) ===
运行正常@ConditionalOnClass:当前环境存在指定的这个类时,才声明该 bean
如果引入了web起步依赖,则使用,负责没有
@ConditionalOnClass(name="org.springframework.web.servlet.DispatcherServlet")
@Bean
public DruidDataSource druidDataSource1() {
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setUsername("root");
druidDataSource.setPassword("123456");
druidDataSource.setUrl("jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC");
druidDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
System.out.println("=== 创建自定义数据源(druidDataSource) ===");
System.out.println("运行正常");
return druidDataSource;
}当在pom文件导入依赖后,运行结果包含以下结果
=== 创建自定义数据源(druidDataSource) ===
运行正常在实际开发中,我们经常定义公共组件给开发团队使用,为了让他们使用更方便,我们会将公共组件自定义starter,如果自定义starter,需要知道自动配置原理。(面试也会问到)
自动配置:遵循约定大于配置的原则,在boot程序启动后,起步依赖中的一些bean对象会自动注入到ioc容器。
大于配置:SpringBoot的核心设计理念"约定优于配置",即大多数场景下不用写繁琐配置,约定开发就能跑通;只有需要自定义时,才需要写少量配置覆盖约定;
启动类加了 @SpringBootApplication,这个注解里藏着「自动配置开关」;
开关会通过 @Import 导入一个特殊类,这个类会去读配置文件里的「要创建的 Bean 全类名」;
每个要创建的 Bean 都带了 @ConditionalOnXXX(比如 @ConditionalOnClass):只有你项目里引入了对应的依赖(比如 Druid 包),条件才满足;
条件满足后,通过 @Bean 注解的方法,把 Bean 自动加载进 IoC 容器。
标准答案
1.在主启动类上添加了SpringBootApplication注解,这个注解组合了EnableAutoConfiguration注解
2.EnableAutoConfiguration注解又组合了import注解,导入了AutoConfigurationImportSelector类
3.实现了selectImports方法,这个方法经过层层调用,最终读取到META-INF目录下,后缀名为imports的文件,如果是Boot2.7以前的版本,读取的是spring.factories文件
4.在这个文件包含了很多全类名,SpringBoot读取到了全类名后,会解析注册条件,也就是@Conditional及其衍生注解,把满足注册条件的Bean对象自动注入到IOC容器中
从启动类的注解@SpringBootApplication开始。
1.该注解是一个组合注解,里面共有多个注解,其中@EnableAutoConfiguration为核心注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("略")
public @interface SpringBootApplication {
//略
}拓展:在@SpringBootConfiguration中,含有@Configuration,这说明了启动类实际上也属于配置类。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@Indexed
public @interface SpringBootConfiguration {
@AliasFor(
annotation = Configuration.class
)
boolean proxyBeanMethods() default true;
}2.@EnableAutoConfiguration类似于自动配置开关,通过@Import导入了特殊类AutoConfigurationImportSelector
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {//略}3.在AutoConfigurationImportSelector中继承了ImportSelector的selectImports方法
继承路线:AutoConfigurationImportSelector --> DeferredImportSelector -->ImportSelector
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
}4.上述方法主要用到了autoConfigurationEntry,来源(层层调用)来自于META-INF/spring/,存在于在起步依赖的autoconfigure中,也就是一个配置文件,记录了「要创建的 Bean 全类名」;
在SpringBoot2.7以前,这个配置文件主要是spring.factories 在SpringBoot2.7~3.0之间,这个配置文件主要是spring.factories和org.springframework.boot.autoconfigure.AutoConfiguration.imports(即.imports文件) 在SpringBoot3.0之后,这个配置文件只支持.imports文件
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test-autoconfigure</artifactId>
<version>3.5.8</version>
<scope>compile</scope>
</dependency>
5.进入其中一个已经导入依赖的全类名,发现上述注解
@AutoConfigureOrder(Integer.MIN_VALUE)
@AutoConfiguration(
after = {ServletWebServerFactoryAutoConfiguration.class}
)
@ConditionalOnWebApplication(
type = Type.SERVLET
)
@ConditionalOnClass(DispatcherServlet.class)
public class DispatcherServletAutoConfiguration {//略}@AutoConfiguration组合注解中包含@Configuration,说明这是一个配置类@ConditionalOnClass,即如果不引入依赖,就不注入到IoC容器中。6.在同样的类下面有着多个方法,其中注入Bean的方法写法与上述讲过的一致
@Bean(
name = {"dispatcherServlet"}
)
public DispatcherServlet dispatcherServlet(WebMvcProperties webMvcProperties) {
DispatcherServlet dispatcherServlet = new DispatcherServlet();
dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest());
dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest());
dispatcherServlet.setPublishEvents(webMvcProperties.isPublishRequestHandledEvents());
dispatcherServlet.setEnableLoggingRequestDetails(webMvcProperties.isLogRequestDetails());
return dispatcherServlet;
}通过源码,我们如果想让第三方依赖自动配置,我们需要有以下操作
1.提供配置类Config
2.提供自动配置类,并添加@AutoConfiguration、@Import(配置类.class)
3.提供.imports配置文件
4.将全类名配置进配置文件
在实际开发中,经常会定义一些公共组件,提供给各个项目团队使用。而在SpringBoot项目中,一般会将这些公共组件封装为SpringBoot的starter。
Mybatis示例:一般会有两个文件
其中第一个是自动配置功能(autoconfigure),第二个是依赖管理功能(starter),在starter中会引入autoconfigure
需求:自定义mybatis的starter。
步骤拆分:
1.创建 dmybatis-spring-boot-autoconfigure 模块,提供自动配置功能,并自定义配置文件 META-INF/spring/xxx.imports
2.创建 dmybatis-spring-boot-starter 模块,在starter中引入自动配置模块
制作过程
1.创建两个Maven工程,选择quickstart骨架,对标autoconfigure与starter

2.在autoconfigure对应模块引入相关依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>3.5.8</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<version>3.5.8</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.19</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>3.0.5</version>
</dependency>
</dependencies>3.建立配置类,添加注解及对应Bean
@AutoConfiguration //表示当前类是一个自动配置类
public class MyBatisAutoConfig {
//SqlSessionFactoryBean
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
return sqlSessionFactoryBean;
}
//MapperScannerConfigure
@Bean
public MapperScannerConfigurer mapperScannerConfigurer(BeanFactory beanFactory){
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
//扫描的包:启动类所在的包及其子包
List<String> packages = AutoConfigurationPackages.get(beanFactory);
String p = packages.get(0);
mapperScannerConfigurer.setBasePackage(p);
//扫描的注解:
mapperScannerConfigurer.setAnnotationClass(Mapper.class);
return mapperScannerConfigurer;
}
}Mybatis操作数据库核心依赖
SqlSessionFactory和Mapper接口扫描器两个组件
4.创建resources文件,按照自动装配依赖的目录进行创建,并存入全类名


到这里,AutoConfig就已经结束了。
5.引入刚刚制作的AutoConfigure依赖以及其内置的依赖
<dependency>
<groupId>com.coolipa</groupId>
<artifactId>dmybatis-spring-boot-autoconfigure</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>6.配置编译插件(否则Maven默认使用JDK1.5)
在这里,很多人会可以直接跑也不报错,这是因为由两个"隐形兜底" 1.在IDEA中,会自动覆盖Maven配置,根据本地JDK版本,直接使用对应JDK版本进行编译,忽略 Maven 的1.5默认值 2.本地的JDK是8+,在大部分情况下,高版本JDK也能兼容1.5的字节码,不会报错。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.12.1</version>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins>
</build>在后续的实战篇中,将分为
前端篇和后端篇进行讲解 前端篇模块:Vue局部使用、Vue工程化、Element Plus组件库 后端篇模块:业务必备知识、安全体系、进阶能力、环境与运维