From 9b3a71c2cb00a72e3d225d1a9ffaf960d25d754e Mon Sep 17 00:00:00 2001 From: Guide Date: Wed, 4 Sep 2024 16:13:41 +0800 Subject: [PATCH] =?UTF-8?q?[docs=20update]IoC=E5=92=8CAOP=E8=AF=A6?= =?UTF-8?q?=E8=A7=A3=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/.vuepress/theme.ts | 32 +++++++++---------- docs/java/io/io-basis.md | 4 ++- docs/open-source-project/system-design.md | 7 +++- .../framework/spring/ioc-and-aop.md | 20 +++++++++--- .../spring/spring-common-annotations.md | 6 +++- .../spring-knowledge-and-questions-summary.md | 4 ++- 6 files changed, 48 insertions(+), 25 deletions(-) diff --git a/docs/.vuepress/theme.ts b/docs/.vuepress/theme.ts index 2e0317e6..b3e201f4 100644 --- a/docs/.vuepress/theme.ts +++ b/docs/.vuepress/theme.ts @@ -45,22 +45,22 @@ export default hopeTheme({ components: { rootComponents: { // https://plugin-components.vuejs.press/zh/guide/utilities/notice.html#%E7%94%A8%E6%B3%95 - notice: [ - { - path: "/", - title: "PDF面试资料(2024版)", - showOnce: true, - content: - "2024最新版原创PDF面试资料来啦!涵盖 Java 核心、数据库、缓存、分布式、设计模式、智力题等内容,非常全面!", - actions: [ - { - text: "点击领取", - link: "https://oss.javaguide.cn/backend-notekbook/official-account-traffic-backend-notebook-with-data-screenshot.png", - type: "primary", - }, - ], - }, - ], + // notice: [ + // { + // path: "/", + // title: "PDF面试资料(2024版)", + // showOnce: true, + // content: + // "2024最新版原创PDF面试资料来啦!涵盖 Java 核心、数据库、缓存、分布式、设计模式、智力题等内容,非常全面!", + // actions: [ + // { + // text: "点击领取", + // link: "https://oss.javaguide.cn/backend-notekbook/official-account-traffic-backend-notebook-with-data-screenshot.png", + // type: "primary", + // }, + // ], + // }, + // ], }, }, diff --git a/docs/java/io/io-basis.md b/docs/java/io/io-basis.md index 0dd36b1c..a2e6f21d 100755 --- a/docs/java/io/io-basis.md +++ b/docs/java/io/io-basis.md @@ -184,7 +184,9 @@ The content read from file:§å®¶å¥½ 因此,I/O 流就干脆提供了一个直接操作字符的接口,方便我们平时对字符进行流操作。如果音频文件、图片等媒体文件用字节流比较好,如果涉及到字符的话使用字符流比较好。 -字符流默认采用的是 `Unicode` 编码,我们可以通过构造方法自定义编码。顺便分享一下之前遇到的笔试题:常用字符编码所占字节数?`utf8` :英文占 1 字节,中文占 3 字节,`unicode`:任何字符都占 2 个字节,`gbk`:英文占 1 字节,中文占 2 字节。 +字符流默认采用的是 `Unicode` 编码,我们可以通过构造方法自定义编码。 + +Unicode 本身只是一种字符集,它为每个字符分配一个唯一的数字编号,并没有规定具体的存储方式。UTF-8、UTF-16、UTF-32 都是 Unicode 的编码方式,它们使用不同的字节数来表示 Unicode 字符。例如,UTF-8 :英文占 1 字节,中文占 3 字节。 ### Reader(字符输入流) diff --git a/docs/open-source-project/system-design.md b/docs/open-source-project/system-design.md index f4e62287..cf58d706 100644 --- a/docs/open-source-project/system-design.md +++ b/docs/open-source-project/system-design.md @@ -72,7 +72,7 @@ icon: "xitongsheji" - [MyBatis-Plus](https://github.com/baomidou/mybatis-plus) : [MyBatis](http://www.mybatis.org/mybatis-3/) 增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。 - [MyBatis-Flex](https://gitee.com/mybatis-flex/mybatis-flex):一个优雅的 MyBatis 增强框架,无其他任何第三方依赖,支持 CRUD、分页查询、多表查询、批量操作。 - [jOOQ](https://github.com/jOOQ/jOOQ):用 Java 编写 SQL 的最佳方式。 -- [Redisson](https://github.com/redisson/redisson "redisson"):Redis 基础上的一个 Java 驻内存数据网格(In-Memory Data Grid),支持超过 30 个对象和服务:`Set`,`SortedSet`, `Map`, `List`, `Queue`, `Deque` ……,并且提供了多种分布式锁的实现。更多介绍请看:[《Redisson 项目介绍》](https://github.com/redisson/redisson/wiki/Redisson%E9%A1%B9%E7%9B%AE%E4%BB%8B%E7%BB%8D "Redisson项目介绍")。 +- [Redisson](https://github.com/redisson/redisson "redisson"):Redisson 是一款架设在 Redis 基础之上的 Java 驻内存数据网格 (In-Memory Data Grid),它充分利用了 Redis 键值数据库的优势,为 Java 开发者提供了一系列具有分布式特性的常用工具类。例如,分布式 Java 对象(`Set`,`SortedSet`,`Map`,`List`,`Queue`,`Deque` 等)、分布式锁等。详细介绍请看:[Redisson 项目介绍](https://github.com/redisson/redisson/wiki/Redisson%E9%A1%B9%E7%9B%AE%E4%BB%8B%E7%BB%8D "Redisson项目介绍")。 ### 数据同步 @@ -152,6 +152,11 @@ icon: "xitongsheji" 相关阅读:[Skywalking 官网对于主流开源链路追踪系统的对比](https://skywalking.apache.org/zh/blog/2019-03-29-introduction-of-skywalking-and-simple-practice.html) +### 分布式锁 + +- [Lock4j](https://gitee.com/baomidou/lock4j):支持 Redisson、ZooKeeper 等不同方案的高性能分布式锁。 +- [Redisson](https://github.com/redisson/redisson "redisson"):Redisson 在分布式锁方面提供全面且强大的支持,超越了简单的 Redis 锁实现。 + ## 高性能 ### 多线程 diff --git a/docs/system-design/framework/spring/ioc-and-aop.md b/docs/system-design/framework/spring/ioc-and-aop.md index a53e08bf..749d267c 100644 --- a/docs/system-design/framework/spring/ioc-and-aop.md +++ b/docs/system-design/framework/spring/ioc-and-aop.md @@ -36,7 +36,7 @@ IoC (Inversion of Control )即控制反转/反转控制。它是一种思想 - **控制** :指的是对象创建(实例化、管理)的权力 - **反转** :控制权交给外部环境(IoC 容器) -![IoC 图解](https://oss.javaguide.cn/java-guide-blog/frc-365faceb5697f04f31399937c059c162.png) +![IoC 图解](https://oss.javaguide.cn/github/javaguide/system-design/framework/spring/IoC&Aop-ioc-illustration.png) ### IoC 解决了什么问题? @@ -49,17 +49,15 @@ IoC 的思想就是两方之间不互相依赖,由第三方容器来管理相 在没有使用 IoC 思想的情况下,Service 层想要使用 Dao 层的具体实现的话,需要通过 new 关键字在`UserServiceImpl` 中手动 new 出 `IUserDao` 的具体实现类 `UserDaoImpl`(不能直接 new 接口类)。 -![](https://oss.javaguide.cn/github/javaguide/system-design/framework/spring/ioc-kfji3.png) - 很完美,这种方式也是可以实现的,但是我们想象一下如下场景: 开发过程中突然接到一个新的需求,针对`IUserDao` 接口开发出另一个具体实现类。因为 Server 层依赖了`IUserDao`的具体实现,所以我们需要修改`UserServiceImpl`中 new 的对象。如果只有一个类引用了`IUserDao`的具体实现,可能觉得还好,修改起来也不是很费力气,但是如果有许许多多的地方都引用了`IUserDao`的具体实现的话,一旦需要更换`IUserDao` 的实现方式,那修改起来将会非常的头疼。 -![](https://oss.javaguide.cn/github/javaguide/system-design/framework/spring/why-ioc.png) +![IoC&Aop-ioc-illustration-dao-service](https://oss.javaguide.cn/github/javaguide/system-design/framework/spring/IoC&Aop-ioc-illustration-dao-service.png) 使用 IoC 的思想,我们将对象的控制权(创建、管理)交由 IoC 容器去管理,我们在使用的时候直接向 IoC 容器 “要” 就可以了 -![](https://oss.javaguide.cn/github/javaguide/system-design/framework/spring/why-ioc-2.png) +![](https://oss.javaguide.cn/github/javaguide/system-design/framework/spring/IoC&Aop-ioc-illustration-dao.png) ### IoC 和 DI 有区别吗? @@ -87,6 +85,8 @@ AOP 的目的是将横切关注点(如日志记录、事务管理、权限控 AOP 之所以叫面向切面编程,是因为它的核心思想就是将横切关注点从核心业务逻辑中分离出来,形成一个个的**切面(Aspect)**。 +![面向切面编程图解](https://oss.javaguide.cn/github/javaguide/system-design/framework/spring/aop-program-execution.jpg) + 这里顺带总结一下 AOP 关键术语(不理解也没关系,可以继续往下看): - **横切关注点(cross-cutting concerns)** :多个类或对象中的公共行为(如日志记录、事务管理、权限控制、接口限流、接口幂等等)。 @@ -96,6 +96,16 @@ AOP 之所以叫面向切面编程,是因为它的核心思想就是将横切 - **切点(Pointcut)**:一个切点是一个表达式,它用来匹配哪些连接点需要被切面所增强。切点可以通过注解、正则表达式、逻辑运算等方式来定义。比如 `execution(* com.xyz.service..*(..))`匹配 `com.xyz.service` 包及其子包下的类或接口。 - **织入(Weaving)**:织入是将切面和目标对象连接起来的过程,也就是将通知应用到切点匹配的连接点上。常见的织入时机有两种,分别是编译期织入(Compile-Time Weaving 如:AspectJ)和运行期织入(Runtime Weaving 如:AspectJ、Spring AOP)。 +### AOP 常见的通知类型有哪些? + +![](https://oss.javaguide.cn/github/javaguide/system-design/framework/spring/aspectj-advice-types.jpg) + +- **Before**(前置通知):目标对象的方法调用之前触发 +- **After** (后置通知):目标对象的方法调用之后触发 +- **AfterReturning**(返回通知):目标对象的方法调用完成,在返回结果值之后触发 +- **AfterThrowing**(异常通知):目标对象的方法运行中抛出 / 触发异常后触发。AfterReturning 和 AfterThrowing 两者互斥。如果方法调用成功无异常,则会有返回值;如果方法抛出了异常,则不会有返回值。 +- **Around** (环绕通知):编程式控制目标对象的方法调用。环绕通知是所有通知类型中可操作范围最大的一种,因为它可以直接拿到目标对象,以及要执行的方法,所以环绕通知可以任意的在目标对象的方法调用前后搞事,甚至不调用目标对象的方法 + ### AOP 解决了什么问题? OOP 不能很好地处理一些分散在多个类或对象中的公共行为(如日志记录、事务管理、权限控制、接口限流、接口幂等等),这些行为通常被称为 **横切关注点(cross-cutting concerns)** 。如果我们在每个类或对象中都重复实现这些行为,那么会导致代码的冗余、复杂和难以维护。 diff --git a/docs/system-design/framework/spring/spring-common-annotations.md b/docs/system-design/framework/spring/spring-common-annotations.md index 521d7cd4..57ec89ca 100644 --- a/docs/system-design/framework/spring/spring-common-annotations.md +++ b/docs/system-design/framework/spring/spring-common-annotations.md @@ -358,7 +358,11 @@ class WebSite { **数据的校验的重要性就不用说了,即使在前端对数据进行校验的情况下,我们还是要对传入后端的数据再进行一遍校验,避免用户绕过浏览器直接通过一些 HTTP 工具直接向后端请求一些违法数据。** -**JSR(Java Specification Requests)** 是一套 JavaBean 参数校验的标准,它定义了很多常用的校验注解,我们可以直接将这些注解加在我们 JavaBean 的属性上面,这样就可以在需要校验的时候进行校验了,非常方便! +Bean Validation 是一套定义 JavaBean 参数校验标准的规范 (JSR 303, 349, 380),它提供了一系列注解,可以直接用于 JavaBean 的属性上,从而实现便捷的参数校验。 + +- **JSR 303 (Bean Validation 1.0):** 奠定了基础,引入了核心校验注解(如 `@NotNull`、`@Size`、`@Min`、`@Max` 等),定义了如何通过注解的方式对 JavaBean 的属性进行校验,并支持嵌套对象校验和自定义校验器。 +- **JSR 349 (Bean Validation 1.1):** 在 1.0 基础上进行扩展,例如引入了对方法参数和返回值校验的支持、增强了对分组校验(Group Validation)的处理。 +- **JSR 380 (Bean Validation 2.0):** 拥抱 Java 8 的新特性,并进行了一些改进,例如支持 `java.time` 包中的日期和时间类型、引入了一些新的校验注解(如 `@NotEmpty`, `@NotBlank`等)。 校验的时候我们实际用的是 **Hibernate Validator** 框架。Hibernate Validator 是 Hibernate 团队最初的数据校验框架,Hibernate Validator 4.x 是 Bean Validation 1.0(JSR 303)的参考实现,Hibernate Validator 5.x 是 Bean Validation 1.1(JSR 349)的参考实现,目前最新版的 Hibernate Validator 6.x 是 Bean Validation 2.0(JSR 380)的参考实现。 diff --git a/docs/system-design/framework/spring/spring-knowledge-and-questions-summary.md b/docs/system-design/framework/spring/spring-knowledge-and-questions-summary.md index edd21080..7ec32178 100644 --- a/docs/system-design/framework/spring/spring-knowledge-and-questions-summary.md +++ b/docs/system-design/framework/spring/spring-knowledge-and-questions-summary.md @@ -590,7 +590,9 @@ Spring AOP 已经集成了 AspectJ ,AspectJ 应该算的上是 Java 生态系 如果我们的切面比较少,那么两者性能差异不大。但是,当切面太多的话,最好选择 AspectJ ,它比 Spring AOP 快很多。 -### AspectJ 定义的通知类型有哪些? +### AOP 常见的通知类型有哪些? + +![](https://oss.javaguide.cn/github/javaguide/system-design/framework/spring/aspectj-advice-types.jpg) - **Before**(前置通知):目标对象的方法调用之前触发 - **After** (后置通知):目标对象的方法调用之后触发