1
0
mirror of https://github.com/Snailclimb/JavaGuide synced 2025-08-01 16:28:03 +08:00

[docs updete]typo

This commit is contained in:
Guide 2024-08-21 12:26:42 +08:00
parent 2d6445071e
commit f2b24072b5
3 changed files with 81 additions and 8 deletions

View File

@ -69,7 +69,7 @@ mysql> explain SELECT * FROM dept_emp WHERE emp_no IN (SELECT emp_no FROM dept_e
### id
SELECT 标识符,是查询中 SELECT 的序号,用来标识整个查询中 SELELCT 语句的顺序。
`SELECT` 标识符,用于标识每个 `SELECT` 语句的执行顺序。
id 如果相同从上往下依次执行。id 不同id 值越大,执行优先级越高,如果行引用其他行的并集结果,则该值可以为 NULL。
@ -94,7 +94,9 @@ id 如果相同从上往下依次执行。id 不同id 值越大,执行
### type重要
查询执行的类型描述了查询是如何执行的。所有值的顺序从最优到最差排序为system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
查询执行的类型,描述了查询是如何执行的。所有值的顺序从最优到最差排序为:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
常见的几种类型具体含义如下:

View File

@ -423,8 +423,6 @@ CAS 经常会用到自旋操作来进行重试,也就是不成功就一直循
#### 只能保证一个共享变量的原子操作
CAS 只对单个共享变量有效,当操作涉及跨多个共享变量时 CAS 无效。但是从 JDK 1.5 开始,提供了`AtomicReference`类来保证引用对象之间的原子性,你可以把多个变量放在一个对象里来进行 CAS 操作.所以我们可以使用锁或者利用`AtomicReference`类把多个共享变量合并成一个共享变量来操作。
CAS 操作仅能对单个共享变量有效。当需要操作多个共享变量时CAS 就显得无能为力。不过,从 JDK 1.5 开始Java 提供了`AtomicReference`类,这使得我们能够保证引用对象之间的原子性。通过将多个变量封装在一个对象中,我们可以使用`AtomicReference`来执行 CAS 操作。
除了 `AtomicReference` 这种方式之外,还可以利用加锁来保证。

View File

@ -279,6 +279,78 @@ private SmsService smsService;
- 当一个接口存在多个实现类的情况下,`@Autowired``@Resource`都需要通过名称才能正确匹配到对应的 Bean。`Autowired` 可以通过 `@Qualifier` 注解来显式指定名称,`@Resource`可以通过 `name` 属性来显式指定名称。
- `@Autowired` 支持在构造函数、方法、字段和参数上使用。`@Resource` 主要用于字段和方法上的注入,不支持在构造函数或参数上使用。
### 注入 Bean 的方式有哪些?
依赖注入 (Dependency Injection, DI) 的常见方式:
1. 构造函数注入:通过类的构造函数来注入依赖项。
1. Setter 注入:通过类的 Setter 方法来注入依赖项。
1. Field字段 注入:直接在类的字段上使用注解(如 `@Autowired``@Resource`)来注入依赖项。
构造函数注入示例:
```java
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
//...
}
```
Setter 注入示例:
```java
@Service
public class UserService {
private UserRepository userRepository;
// 在 Spring 4.3 及以后的版本,特定情况下 @Autowired 可以省略不写
@Autowired
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
//...
}
```
Field 注入示例:
```java
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
//...
}
```
### 构造函数注入还是 Setter 注入?
Spring 官方有对这个问题的回答:<https://docs.spring.io/spring-framework/reference/core/beans/dependencies/factory-collaborators.html#beans-setter-injection>
我这里主要提取总结完善一下 Spring 官方的建议。
**Spring 官方推荐构造函数注入**,这种注入方式的优势如下:
1. 依赖完整性:确保所有必需依赖在对象创建时就被注入,避免了空指针异常的风险。
2. 不可变性:有助于创建不可变对象,提高了线程安全性。
3. 初始化保证:组件在使用前已完全初始化,减少了潜在的错误。
4. 测试便利性:在单元测试中,可以直接通过构造函数传入模拟的依赖项,而不必依赖 Spring 容器进行注入。
构造函数注入适合处理**必需的依赖项**,而 **Setter 注入** 则更适合**可选的依赖项**,这些依赖项可以有默认值或在对象生命周期中动态设置。虽然 `@Autowired` 可以用于 Setter 方法来处理必需的依赖项,但构造函数注入仍然是更好的选择。
在某些情况下(例如第三方类不提供 Setter 方法),构造函数注入可能是**唯一的选择**。
### Bean 的作用域有哪些?
Spring 中 Bean 的作用域通常有下面几种:
@ -802,7 +874,7 @@ class B {
`@Lazy` 用来标识类是否需要懒加载/延迟加载,可以作用在类上、方法上、构造器上、方法参数上、成员变量中。
Spring Boot 2.2 新增了全局懒加载属性,开启后全局 bean 被设置为懒加载,需要时再去创建。
Spring Boot 2.2 新增了**全局懒加载属性**,开启后全局 bean 被设置为懒加载,需要时再去创建。
配置文件配置全局懒加载:
@ -829,11 +901,12 @@ springApplication.run(args);
- 由于在 A 上标注了 `@Lazy` 注解,因此 Spring 会去创建一个 B 的代理对象,将这个代理对象注入到 A 中的 B 属性;
- 之后开始执行 B 的实例化、初始化,在注入 B 中的 A 属性时,此时 A 已经创建完毕了,就可以将 A 给注入进去。
通过 `@Lazy` 就解决了循环依赖的注入, 关键点就在于对 A 中的属性 B 进行注入时,注入的是 B 的代理对象,因此不会循环依赖
从上面的加载流程可以看出: `@Lazy` 解决循环依赖的关键点在于代理对象的使用
之前说的发生循环依赖是因为在对 A 中的属性 B 进行注入时,注入的是 B 对象,此时又会去初始化 B 对象,发现 B 又依赖了 A因此才导致的循环依赖。
- **没有 `@Lazy` 的情况下**:在 Spring 容器初始化 `A` 时会立即尝试创建 `B`,而在创建 `B` 的过程中又会尝试创建 `A`,最终导致循环依赖(即无限递归,最终抛出异常)。
- **使用 `@Lazy` 的情况下**Spring 不会立即创建 `B`,而是会注入一个 `B` 的代理对象。由于此时 `B` 仍未被真正初始化,`A` 的初始化可以顺利完成。等到 `A` 实例实际调用 `B` 的方法时,代理对象才会触发 `B` 的真正初始化。
一般是不建议使用循环依赖的,但是如果项目比较复杂,可以使用 `@Lazy` 解决一部分循环依赖的问题
`@Lazy` 能够在一定程度上打破循环依赖链,允许 Spring 容器顺利地完成 Bean 的创建和注入。但这并不是一个根本性的解决方案,尤其是在构造函数注入、复杂的多级依赖等场景中,`@Lazy` 无法有效地解决问题。因此,最佳实践仍然是尽量避免设计上的循环依赖
### SpringBoot 允许循环依赖发生么?