提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 一、初识SpringBoot
- SpringBoot 的主要特点
- 1、自动配置:
- 2、外部化配置:
- 3、嵌入式服务器支持:
- 4、启动器依赖(Starter Dependencies):
- 5、简化依赖管理:
- 6、独立应用:
- 7、开箱即用:
- 二、SpringBoot中配置文件优先级
- Spring Boot 支持以下几种配置文件:
- 配置文件优先级
- 1.命令行参数:
- 2.Java System Properties:
- 3.环境变量:
- 4.Spring 应用上下文中的 @PropertySource 注解:
- 5.Spring Boot 默认配置:
- 项目中默认优先级
- 初识Bean
- 定义Bean对象的常用注解
- @Component:
- @Service:
- @Repository:
- @Controller:
- @RestController:
- @Configuration:
- @Bean:
- 获取Bean的方法
- Bean 的特点
- 依赖注入(Dependency Injection, DI):
- 依赖注入的方式
- 1.构造函数注入(Constructor Injection):
- 2.字段注入(Field Injection):
- 3.setter 方法注入(Setter Injection):
- 依赖注入相关注解
- 1. @Autowired
- 示例:
- 2. @Qualifier
- 示例:
- 3. @Inject
- 示例:
- 4. @Resource
- 示例:
- 5. @Value
- 示例:
- 6. @Primary
- 示例:
- 7. @Scope
- 示例:
- 小结
- 生命周期管理:
- Bean 的生命周期主要包括以下几个阶段:
- 创建:
- 依赖注入:
- 初始化:
- 使用 @PostConstruct 注解:
- 示例:
- 实现 InitializingBean 接口:
- 示例:
- 使用:
- 销毁:
- 小结
- 作用域(Scope):
- 1. Singleton (singleton)
- 特点:
- 2. Prototype (prototype)
- 特点:
- 3. Request (request)
- 特点:
- 4. Session (session)
- 特点:
- 5. Global Session (globalSession)
- 特点:
- 6.Application (application)
- 特点:
- 7. Thread (threadScope)
- 特点:
- 推荐学习资料链接
前言
提示:自己也是刚开始接触springboot,所有希望以一个小白的视角帮助其他新人入门理解springboot
此篇主要是学习理解springboot的配置优先级、Bean管理等springboot原理,帮助初学者进一步学会运用和理解springboot的工作原理。有错误或者需要完善的地方也欢迎大家积极评论指出,一起学习交流与完善!!!
提示:以下是本篇文章正文内容,下面案例可供参考
一、初识SpringBoot
Spring Boot 是一款用于简化 Spring 应用程序开发的框架。它旨在让开发者能够更快速、更简单地创建独立的、生产级别的基于 Spring 的应用。Spring Boot 通过一系列内置的默认配置和约定(Convention over Configuration),使得开发者能够专注于业务逻辑的实现,而不是繁琐的基础配置。
SpringBoot 的主要特点
1、自动配置:
Spring Boot 提供了大量的自动配置选项,这些配置可以自动识别并配置应用程序所需的组件和服务。例如,如果你添加了 Spring Data JPA 的依赖,Spring Boot 会自动配置数据源、实体管理器工厂(EntityManagerFactory)等组件。
2、外部化配置:
Spring Boot 支持外部化配置,允许你将配置从代码中分离出来,放到单独的配置文件(如 application.properties 或 application.yml)中。这样可以更方便地管理和修改配置,而不需要重新编译和部署应用。
3、嵌入式服务器支持:
Spring Boot 默认集成了嵌入式的 Tomcat 服务器,同时也支持其他嵌入式服务器如 Jetty 和 Undertow。这意味着你不需要单独安装和配置应用服务器,可以直接运行 Spring Boot 应用程序。
4、启动器依赖(Starter Dependencies):
Spring Boot 提供了许多启动器依赖(starter dependencies),这些依赖简化了依赖管理。每个启动器包含了一组协调好的依赖,使得添加特定功能变得简单。
5、简化依赖管理:
Spring Boot 内置了对依赖版本的管理,通过 BOM(Bill of Materials)一个用于管理项目依赖版本的重要工具,来简化依赖版本的管理。BOM 使得依赖管理变得更加简单,开发者不需要为每个依赖项指定版本号,而是由 BOM 统一管理。这意味着你不需要显式指定大多数 Spring 框架依赖的版本号,这样可以避免因版本冲突而导致的问题。使用 spring-boot-starter-parent 作为父 POM 可以自动导入 BOM 并管理依赖版本。
6、独立应用:
Spring Boot 应用程序通常被打包成独立的可执行 JAR 或 WAR 文件,不需要额外的部署步骤。这意味着你可以直接运行 JAR 文件来启动应用程序。
开箱即用:
7、开箱即用:
Spring Boot 的一大特点是“开箱即用”,即在不编写任何配置的情况下,可以立即启动一个功能齐全的应用程序。这使得开发人员能够快速搭建并运行应用程序。
这些都是spring boot的一些特点之一,springboot还有很多优点需要去深入学习了解,这里只是简单提一下,因为此次学习主要内容在下面章节中。
二、SpringBoot中配置文件优先级
Spring Boot 支持多种配置文件格式,并且可以根据不同的需求和场景使用不同的配置文件。了解配置文件的优先级对于管理应用的配置至关重要。
Spring Boot 支持以下几种配置文件:
1、application.properties,以properties后缀的配置文件,或application.yml,以yml后缀的配置文件,或application.yaml,以yaml后缀的配置文件;
2、application-{profile}.properties 或 application-{profile}.yml或application-{profile}.yaml:
当激活了特定的 Spring Profile 时,会使用这些配置文件。例如,当激活 dev profile 时,会使用 application-dev.properties 或 application-dev.yml等。
3、bootstrap.properties 或 bootstrap.yml或bootstrap.yaml:
这些文件用于引导应用程序,通常用于配置加密/解密密钥等。它们的优先级通常低于 application.properties 或 application.yml\application.yaml。
在同一级目录下
不同后缀配置文件的优先级:properties(最高) > yml > yaml(最低)
相同后缀配置文件的优先级:application-xxx.yml > application.yml
配置文件优先级
Spring Boot 决定配置文件优先级的顺序如下:
1.命令行参数:
最高的优先级,直接覆盖所有其他配置。可以通过命令行参数直接传递配置,如 --server.port=8080。这是最高的优先级。
java -jar xxx.jar --server.port=8080
2.Java System Properties:
通过 -Dproperty=value 设置的系统属性具有较高的优先级。
3.环境变量:
通过环境变量设置的配置具有较高的优先级。
4.Spring 应用上下文中的 @PropertySource 注解:
通过 @PropertySource 注解指定的额外属性文件具有较高的优先级。
5.Spring Boot 默认配置:
Spring Boot 提供的默认配置,如果没有其他配置则会被使用。
项目中默认优先级
● 项目名/config/xxx.properties(优先级最高)
● 项目名/src/main/resources/config/xxx.properties
● 项目名/src/main/resources/xxx.yml (优先级最低)
application.properties 或 application.yml 文件:
通常位于类路径的 src/main/resources 目录下,是默认的配置文件。
application-{profile}.properties 或 application-{profile}.yml 文件:
当激活了特定的 Spring Profile 时,会使用这些配置文件。
bootstrap.properties 或 bootstrap.yml 文件:
用于引导应用程序,优先级低于 application.properties 或 application.yml。
初识Bean
对于初学者来说,可能会疑问什么是Bean 呢?
在 Spring 框架中,Bean 是一个 Java 对象,这些对象通常是 Java 类的实例,它们可以在应用程序中充当各种角色,如服务层组件、数据访问对象、控制器等。它由 Spring IoC(Inverse of Control,控制反转,(留个坑这部分会在另外文章中详细介绍))容器管理。Spring 容器负责创建这些对象,并管理它们的生命周期,包括创建、注入依赖、初始化、使用和销毁等步骤。
在 Spring Boot 中,Bean 的管理是通过 Spring 框架的核心容器来实现的。Spring Boot 利用了 Spring 框架的强大功能来简化 Bean 的管理,使得开发者可以更加专注于业务逻辑的实现,而不是繁琐的基础配置工作。
定义Bean对象的常用注解
在 Spring Boot 中,Bean 的定义通常是通过注解来完成的。以下是常用的注解:
@Component:
用于标记任何非 Service、Repository 或 Controller 的类作为组件。Spring Boot 会自动扫描带有此注解的类,并将其注册为 Bean。
@Service:
用于标记业务逻辑层的类。与 @Component 类似,但更明确地标记为服务层组件。
@Repository:
用于标记数据访问层的类。通常用于处理数据库操作。
@Controller:
用于标记 Web 层的类。处理来自用户的请求,并返回响应。
@RestController:
是 @Controller 和 @ResponseBody 的组合注解,用于标记 RESTful 控制器类。处理来自用户的 RESTful 请求,并返回 JSON/XML 数据。
@Configuration:
用于标记配置类,可以用来定义其他 Bean。通常配合 @Bean 注解使用。
@Bean:
如果要管理的Bean对象来自第三方(不是自己定义的,比如其他jar包中的),是无法用**@Component**等注解的方式声明Bean 的,这个时候就需要用到该注解了。它可以在配置类中使用,用来声明一个具体的 Bean。可以定义 Bean 的作用域、初始化方法等。
如下代码定义中,Service 类被标记为一个 Spring Bean:
@Component
public class Service {public String getHelloWorld() {return "Hello world!";}
}
获取Bean的方法
ApplicationContext 是 Spring 框架中用于管理和获取 bean 的核心接口。它提供了一种更通用的方式来管理 Spring 容器。
这部分就简单提一下,主要的还是在下面,感兴趣可以查看其他相关文章帮助了解,如:SpringBoot获取bean的几种方式
黑马 第三方bean
Bean 的特点
既然了解了怎么定义bean和获取bean,那么接下来就进一步了解一下Bean 的几个特点吧。
依赖注入(Dependency Injection, DI):
Bean 通常通过依赖注入来获取它们所依赖的对象。依赖注入是一种设计模式,它允许将对象的依赖项在其创建过程中注入,而不是在对象内部创建或查找依赖项。
依赖注入的主要目的是为了降低模块间的耦合度,提高代码的可测试性和灵活性。通过依赖注入,对象不再需要关心依赖项的创建和管理,只需要声明它需要哪些依赖即可。
说了一堆可能对于新人来说还是不太好理解,那么就将这个名词拆开来解释。
依赖(Dependency):
依赖是指一个对象需要其他对象的功能才能正常工作的关系。例如,一个控制器类需要一个服务类来处理业务逻辑,简单点就是你当前的类中需要使用到了其他类中的方法,那么你这个类就是依赖了其他类。
注入(Injection):
注入是指将依赖项传递给需要它的对象的过程。注入可以在构造函数、setter 方法或字段上完成。
通俗讲就是怎么获取到你依赖的其他类的对象,因为你要使用它的方法,首先的需要这样一个对象吧,传统的方式就是在我们写的这个类中new一个对象出来,但是现在不这样操作了,因为借助容器我们可以优雅的通过注入获取。
举个例子:假设我们有两个类:GreetingService 和 GreetingController。GreetingController 依赖于 GreetingService。通过构造函数注入,GreetingService 的实例被注入到 GreetingController 中。
@Service
public class GreetingService {public String getGreeting() {return "Hello from GreetingService!";}
}@RestController
public class GreetingController {private final GreetingService greetingService;//构造函数注入的方式@Autowiredpublic GreetingController(GreetingService greetingService) {this.greetingService = greetingService;}@GetMapping("/greet")public String greet() {return greetingService.getGreeting();}
}
依赖注入的方式
在 Spring Boot 中,依赖注入主要通过以下几种方式实现:
1.构造函数注入(Constructor Injection):
依赖项通过构造函数传入,保证了依赖关系的不可变性。
@RestController
public class GreetingController {private final GreetingService greetingService;@Autowiredpublic GreetingController(GreetingService greetingService) {this.greetingService = greetingService;}@GetMapping("/greet")public String greet() {return greetingService.getGreeting();}
}
2.字段注入(Field Injection):
依赖项直接注入到类的字段中,这种方式简单但不如构造函数注入安全。
@RestController
public class GreetingController {@Autowiredprivate GreetingService greetingService;@GetMapping("/greet")public String greet() {return greetingService.getGreeting();}
}
3.setter 方法注入(Setter Injection):
依赖项通过 setter 方法注入,不如构造函数注入常见。
@RestController
public class GreetingController {private GreetingService greetingService;@Autowiredpublic void setGreetingService(GreetingService greetingService) {this.greetingService = greetingService;}@GetMapping("/greet")public String greet() {return greetingService.getGreeting();}
}
依赖注入相关注解
在 Spring Boot 中,依赖注入不仅仅限于使用 @Autowired
注解。实际上,Spring 支持多种依赖注入注解,每种注解都有其特定的使用场景和优势。下面详细介绍这些注解及其用法:
1. @Autowired
@Autowired
是最常用的依赖注入注解,它可以用于字段、构造函数、方法或者局部变量上。Spring 会自动寻找与类型匹配的 Bean 并进行注入。
示例:
@RestController
public class GreetingController {@Autowiredprivate GreetingService greetingService;@GetMapping("/greet")public String greet() {return greetingService.getGreeting();}
}
2. @Qualifier
@Qualifier
注解用于解决类型相同但名字不同的 Bean 的注入问题。当存在多个相同类型的 Bean 时,可以通过 @Qualifier
指定具体的 Bean 名称。
示例:
@Service
public class GreetingServiceA implements GreetingService {// 实现 GreetingService 接口
}@Service
public class GreetingServiceB implements GreetingService {// 实现 GreetingService 接口
}@RestController
public class GreetingController {@Autowired@Qualifier("greetingServiceA")private GreetingService greetingService;@GetMapping("/greet")public String greet() {return greetingService.getGreeting();}
}
3. @Inject
@Inject
是 JSR 330 标准的一部分,与 @Autowired
类似,但更强调依赖注入的语义。在 Spring 中,@Inject
也是受支持的。
示例:
@RestController
public class GreetingController {@Injectprivate GreetingService greetingService;@GetMapping("/greet")public String greet() {return greetingService.getGreeting();}
}
4. @Resource
@Resource
是 J2EE 标准的一部分,它可以用于字段或方法上,类似于 @Autowired
。@Resource
可以通过 name
属性指定 Bean 的名称。
示例:
@RestController
public class GreetingController {@Resource(name = "greetingService")private GreetingService greetingService;@GetMapping("/greet")public String greet() {return greetingService.getGreeting();}
}
5. @Value
@Value
注解用于从配置文件中获取值,并将其注入到字段或方法中。通常用于注入基本类型的值,如字符串、整数等。
示例:
@RestController
public class GreetingController {@Value("${greeting.message}")private String greetingMessage;@GetMapping("/greet")public String greet() {return greetingMessage;}
}
6. @Primary
@Primary
注解用于在多个相同类型的 Bean 中指定首选的 Bean。当存在多个相同类型的 Bean 时,@Primary
标记的 Bean 会被优先注入。
示例:
@Service
@Primary
public class GreetingServiceA implements GreetingService {// 实现 GreetingService 接口
}@Service
public class GreetingServiceB implements GreetingService {// 实现 GreetingService 接口
}@RestController
public class GreetingController {@Autowiredprivate GreetingService greetingService;@GetMapping("/greet")public String greet() {return greetingService.getGreeting();}
}
7. @Scope
@Scope
注解用于指定 Bean 的作用域,默认是 singleton
。可以设置为 prototype
、request
、session
或 globalSession
等。
示例:
@Service
@Scope("prototype")
public class GreetingService {// ...
}
小结
在 Spring Boot 中,依赖注入可以通过多种注解来实现,每种注解都有其特定的使用场景和优势:
@Autowired
是最常用的依赖注入注解。@Qualifier
用于解决类型相同但名字不同的 Bean 的注入问题。@Inject
是 JSR 330 标准的一部分,强调依赖注入的语义。@Resource
是 J2EE 标准的一部分,可以指定 Bean 的名称。@Value
用于从配置文件中获取值。@Bean
用于定义新的 Bean。@Primary
用于在多个相同类型的 Bean 中指定首选的 Bean。@Scope
用于指定 Bean 的作用域。
生命周期管理:
推荐视频:史上最完整的SpringBean的生命周期
Spring 容器不仅负责创建 Bean,还负责管理 Bean 的生命周期。这意味着 Spring 容器会在适当的时候调用 Bean 的初始化方法和销毁方法。下面这些阶段有个大致了解就ok,因为Spring 容器会帮助我们进行管理,不需要人工管理。
Bean 的生命周期主要包括以下几个阶段:
创建:
1.解析 Bean 定义: Spring 会解析配置类中的 @Bean 方法,或者基于注解(如 @Component, @Service, @Repository, @Controller)创建 Bean 的定义。
2.实例化 Bean: Spring 容器会根据 Bean 的定义创建一个新的实例。
依赖注入:
Spring 容器为 Bean 注入其依赖的其他 Bean。如果 Bean 的依赖项也是由 Spring 容器管理的,则这些依赖项也会按照相应的生命周期进行创建和注入。
初始化:
Spring 容器调用 Bean 的初始化方法(如果有的话)。初始化方法通常通过 @PostConstruct 注解或在 XML 配置中指定。也可以通过实现 InitializingBean 接口来定义初始化方法。在 XML 配置文件中使用 标签的 init-method 属性来指定初始化方法。
初始化方法有两种常见的定义方式:
使用 @PostConstruct 注解:
可以在任何非私有的无参方法上使用 @PostConstruct 注解来标记该方法为初始化方法。
示例:
@Service
public class GreetingService {@PostConstructpublic void initialize() {System.out.println("Initializing GreetingService");}public String getGreeting() {return "Hello from GreetingService!";}
}
实现 InitializingBean 接口:
实现 InitializingBean 接口并重写 afterPropertiesSet() 方法。
示例:
@Service
public class GreetingService implements InitializingBean {@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("Initializing GreetingService via InitializingBean");}public String getGreeting() {return "Hello from GreetingService!";}
}
使用:
Bean 被应用程序使用。
销毁:
在应用程序关闭时,Spring 容器调用 Bean 的销毁方法(如果有的话)。
销毁方法通常通过 @PreDestroy 注解或在 XML 配置中指定。
也可以通过实现 DisposableBean 接口来定义销毁方法。
小结
在 Spring Boot 中,Bean 的初始化并不是在创建的时候立即执行的,而是等到所有的依赖注入都完成之后才进行。这种设计可以确保 Bean 在初始化之前已经具备了所有必要的依赖项,并且可以更好地管理资源。通过遵循这样的生命周期顺序,可以保证 Bean 在使用前处于正确的状态,增强系统的稳定性和可靠性。并且,Bean 的创建、初始化和销毁是由 Spring 容器自动完成的。
作用域(Scope):
推荐视频:黑马视频
推荐文章:Spring Bean Scope 指南
Bean 可以有不同的作用域,这决定了 Bean 的生存周期和可见性。不同的作用域意味着不同的实例化和销毁策略。理解 Bean 的作用域对于正确管理和优化应用程序的性能至关重要。常见的作用域包括 Singleton、Prototype、Request、Session 和 GlobalSession、Application、Thread 。通常在类定义上使用 @Scope 注解,并指定作用域名称。重点了解前两种就可以。
1. Singleton (singleton)
定义: 默认的作用域,表示在整个应用程序上下文中只有一个 Bean 实例存在。每次请求该 Bean 时,返回的是同一个实例。
对于 singleton 作用域的 Bean:初始化方法会在 Bean 被创建并注入依赖后立即执行。
特点:
单例模式: 在整个应用程序生命周期内,只有一个实例。
共享资源: 适合需要共享状态或配置信息的 Bean。
缓存友好: 适合需要缓存结果的场景。
2. Prototype (prototype)
定义: 表示每次请求该 Bean 时都会创建一个新的实例。
对于 prototype 作用域的 Bean:初始化方法会在每次创建新实例后立即执行。
特点:
每次请求新建实例: 适合需要独立状态的场景。
线程安全: 每个请求有自己的实例,不存在线程安全问题。
不适合缓存: 每次请求都会创建新实例,不适合缓存结果。
@Component
@Scope("prototype")
public class PrototypeService {public String getMessage() {return "Prototype Service";}
}
3. Request (request)
定义: 表示在一个 HTTP 请求的生命周期内,只有一个 Bean 实例存在。每个请求有自己的 Bean 实例。
特点:
请求范围: 每个 HTTP 请求有自己的实例。
线程安全: 适合需要独立状态的场景。
Web 应用程序: 适合 Web 应用程序中的场景。
@Component
@Scope("request")
public class RequestScopedService {public String getMessage() {return "Request Scoped Service";}
}
4. Session (session)
定义: 表示在一个 HTTP Session 的生命周期内,只有一个 Bean 实例存在。每个会话有自己的 Bean 实例。
特点:
会话范围: 每个 HTTP Session 有自己的实例。
线程安全: 适合需要会话级别的状态管理。
Web 应用程序: 适合 Web 应用程序中的场景。
@Component
@Scope("session")
public class SessionScopedService {public String getMessage() {return "Session Scoped Service";}
}
5. Global Session (globalSession)
定义: 表示在一个全局 HTTP Session 的生命周期内,只有一个 Bean 实例存在。适用于 Portlet 环境中的全局会话。
特点:
全局会话范围: 每个全局 HTTP Session 有自己的实例。
Portlet 环境: 适合 Portlet 环境中的场景。
@Component
@Scope("globalSession")
public class GlobalSessionScopedService {public String getMessage() {return "Global Session Scoped Service";}
}
6.Application (application)
定义: 表示在整个 Web 应用程序的生命周期内,只有一个 Bean 实例存在。与 singleton 类似,但在 Web 应用程序上下文中使用更为明确。
特点:
全局唯一: 在整个 Web 应用程序的生命周期内,只有一个实例。
共享资源: 适合需要在整个应用程序范围内共享状态或数据的场景。
Web 应用程序: 主要用于 Web 应用程序中的场景。
import org.springframework.stereotype.Component;
import org.springframework.context.annotation.Scope;@Component
@Scope("application")
public class ApplicationScopedService {public String getMessage() {return "Application Scoped Service";}
}
7. Thread (threadScope)
定义:表示在一个线程的生命周期内,只有一个 Bean 实例存在。每个线程有自己的 Bean 实例。
特点:
线程范围: 每个线程有自己的实例。
线程安全: 适合需要线程级别的状态管理。
并发场景: 适合多线程并发场景中的状态管理。
@Component
@Scope("threadScope")
public class ThreadScopedService {public String getMessage() {return "Thread Scoped Service";}
}
推荐学习资料链接
SpringBoot获取bean的几种方式
史上最完整的SpringBean的生命周期
黑马 第三方bean
黑马视频
Spring Bean Scope 指南