自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(344)
  • 收藏
  • 关注

原创 DDD(领域驱动设计)分层架构

DDD全称为(Domain-DrivenDesign,简称DDD),领域驱动设计。

2022-07-24 16:43:29 10346 4

原创 JUC学习(五):ArrayList的线程安全问题分析与解决方案(vector、Collections、写时复制技术)

目录一、异常演示二、解决方案 1、vector 2、Collections工具类 3、CopyOnWriteArrayList 写时复制技术三、写时复制技术 1、特性 2、原理一、异常演示循环创建线程,将数据放入集合的同时,从集合中读取数据。/** * list集合线程不安全问题 */public class ThreadDemo04 {......

2022-03-21 12:34:28 5269

原创 在面试官面前优雅地种下红黑树

目录前言一、红黑树的基本性质二、为什么要用红黑二叉树1、 二叉搜索树(Binary Search Trees) 2、二叉平衡搜索树(Balanced binary search trees) 3、总结:为什么要用红黑树三、红黑树的插入 1、父节点为黑色 2、父节点为红色,叔叔节点为红色 3、父节点为红、叔叔节点为黑,新节点是祖父节点的右子节点的右子节点(上表中的:右右)...

2022-02-05 22:25:47 665

原创 今天轮到我来撕ConcurrentHashMap了

前言你是否有过这样的经历:信心满满地进入面试房间,慷慨激昂地进行自我介绍,一度以为自己稳操胜券,直到面试官开口:“你是学Java的是吧?那你知道ConcurrentHashMap的实现原理吗?你知道ConcurrentHashMap1.7和1.8的区别吗?你知道ConcurrentHashMap使用什么技术来保证线程安全吗?你能说说ConcurrentHashMap的put()方法吗?跟我说说ConcurrentHashmap 不支持 key 或者 value 为 null 的原因?pu...

2022-02-04 21:22:36 3492

原创 Java后端研发实习生面试知识点总结(持续更新中)

一、Java基础 1、说说spring中的IOC和AOPIOC:IOC容器帮我们创建对象,不需要程序员去手动创建。IOC就像一个工厂一样,当我们需要一个对象的时候,只需要写java代码或者xml文件,IOC就会在适当的时候创建,通过DI自动注入,我们不需要关心这些bean是如何创建的。DI就像打疫苗一样,我们不需要知道疫苗是如何被制造出来的,只需要到指定点去告诉医务人员要打疫苗,相当于编写java代码或者xml文件,医务人员就会将疫苗注入我们体内。IOC还有一个重要的作......

2022-01-15 14:47:24 2165 2

原创 org.apache.ibatis.binding.BindingException: Invalidbound statement (not found)的解决方案和造成原因分析(超详细)

一、问题描述今天使用SpringBoot整合mybaits时报了绑定异常的错误:AbstractHandlerExceptionResolver.java:194 |org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver |Resolved exception caused by handler execution: org.apache.ibatis.b...

2021-12-22 12:28:11 35870 5

原创 重构——改善既有代码的设计

重构改善既有代码的设计-学习(一):封装-CSDN博客。

2024-05-03 00:12:05 971

原创 Effective Java

接口只应该用来定义类型,而不是用来导出常量标明实现了具有某种属性的接口 六、Lambda和表达式。

2024-05-02 23:46:17 536 3

原创 重构改善既有代码的设计-学习(六):处理继承关系

无论何时,只要系统内出现重复,你就会面临“修改其中一个却未能修改另一个”的风险。通常,找出重复也有一定的难度。所以,某个函数在各个子类中的函数体都相同(它们很可能是通过复制粘贴得到的),这就需要使用函数上移,也就是。函数上移过程中,被提升的函数可能会引用只出现于子类而不出现于超类的特性。此时,我就得用和先将这些特性(类或者函数)提升到超类。

2024-01-28 20:11:01 1295

原创 重构改善既有代码的设计-学习(五):重构API

例如: 改为:2、函数参数化(Parameterize Function) 如果两个函数逻辑非常相似,只有一些字面量值不同,可以将其合并成一个函数,以参数的形式传入不同的值,从而消除重复。 “标记参数”是这样的一种参数:调用者用它来指示被调函数应该执行哪一部分逻辑。 标记参数让人难以理解到底有哪些函数可以调用、应该怎么调用。拿到一份API以后,我首先看到的是一系列可供调用的函数,但标记参数却隐藏了函数调用中存在的差异性。使用

2024-01-25 21:29:17 631

原创 重构改善既有代码的设计-学习(四):简化条件逻辑

可以将大块头代码分解为多个独立的函数,根据每个小块代码的用途,为分解而得的新函数命名。对于条件逻辑,将每个分支条件分解成新函数还可以带来更多好处:可以突出条件逻辑,更清楚地表明每个分支的作用,并且突出每个分支的原因。

2024-01-24 23:55:59 1197

原创 重构改善既有代码的设计-学习(三):重新组织数据

1、拆分变量(Split Variable)1、拆分变量(Split Variable)有些变量用于保存一段冗长代码的运算结果,以便稍后使用。这种变量应该只被赋值一次。如果它们被赋值超过一次,就意味它们在函数中承担了一个以上的责任。如果变量承担多个责任,它就应该被替换(分解)为多个变量,每个变量只承担一个责任。同一个变量承担两件不同的事情,会令代码阅读者糊涂。有两种情况除外:循环变量(loop variable)会随循环的每次运行而改变(例如for(let i=0;i

2024-01-23 21:31:38 1108

原创 重构改善既有代码的设计-学习(二):搬移特性

搬移函数这一章节总结起来就是:在不同的上下文之间搬移元素。

2024-01-22 20:18:41 893

原创 重构改善既有代码的设计-学习(一):封装

如果某些客户端先通过服务对象的字段得到另一个对象(受托类),然后调用后者的函数,那么客户就必须知晓这一层委托关系。当一个类因为某种原因开始萎缩(可能是因为一些重构动作移走了这个类的责任),不再承担足够责任,那么他不再有单独存在的理由。例如,本身“图案”这个字段可能只是一个字符串,用来存储一个链接,但后来随着业务的逐渐复杂,开始有尺寸、文案等等,那他们就应该被抽取出来,放在一个类里面。修改的方式是,在类上提供一些修改集合的方法(通常是“添加”、“删除”等),这样就可以使对集合的修改必须经过类。

2024-01-20 19:30:37 1169

原创 Java LinkedList解密

LinkedList其实底层是链表:当初始化的时候,会将链表这个节点的值、prev指针和next指针初始化。

2024-01-03 22:01:28 1053 1

原创 Java ArrayList解密

堆栈过程图示:└── if (size == elementData.length) // 判断是否需要扩容├── grow(minCapacity) // 扩容│ └── newCapacity = oldCapacity + (oldCapacity >> 1) // 计算新的数组容量│ └── Arrays.copyOf(elementData, newCapacity) // 创建新的数组// 添加新元素// 添加成功。

2024-01-01 19:06:14 908

原创 缓存和数据库,1+1如何大于2?

缓存,简单说就是为了节约对原始资源重复获取的开销,而将结果数据副本存放起来以供获取的方式。首先,。我们前面已经多次提到过,当某一个操作是"幂等"的和“安全"的,那么这样的操作就可以被抽象为对"资源"的获取操作,那么它才可以考虑被缓存。有些操作不幂等、不安全,比如银行转账,改变了目标对象的状态,自然就难以被缓存。其次,。缓存能生效的本质是空间换时间。也就是说,将曾经出现过的数据以占据缓存空间的方式存放下来,在下一次的访问时直接返回,从而节约了通过原始流程访问数据的时间。

2023-12-31 17:59:56 748

原创 SQL题记录

Table:id 是这个表的主键。该表包含有关传入事务的信息。state 列类型为 “[”批准“,”拒绝“] 之一。编写一个 sql 查询来查找每个月和每个国家/地区的事务数及其总金额、已批准的事务数及其总金额。以返回结果表。查询结果格式如下所示。

2023-06-10 21:18:10 1041

原创 JVM学习(十四):垃圾收集器(万字介绍CMS、G1)

在JDK 1.5时期,Hotspot推出了一款在强交互应用中几乎可认为有划时代意义的垃圾收集器:CMS (Concurrent-Mark-Sweep)收集器,这款收集器是HotSpot虚拟机中第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程同时工作。CMS收集器的关注点是尽可能缩短垃圾收集时用户线程的停顿时间。停顿时间越短(低延迟)就越适合与用户交互的程序,良好的响应速度能提升用户体验。目前很大一部分的Java应用集中在互联网站或者B/S系统的服务端上,这类应用尤其重视服务的响应速度。

2023-06-02 22:13:15 4911

原创 JVM学习(十三):面试中绕不开的String

String实现了Serializable接口,表示字符串是支持序列化的;实现了Comparable接口,表示String可以比较大小。

2023-05-30 21:43:34 648

原创 JVM学习(十二):执行引擎

大部分的程序代码转换成物理机的目标代码或虚拟机能执行的指令集之前,都需要经过上图中的各个步骤。其中,黄色是javac前端编译器编译的过程,绿色是解释执行的过程,蓝色是编译执行的过程。1、什么是解释器(Interpreter),什么是JIT编译器?解释器:当Java虚拟机启动时会根据预定义的规范对字节码采用逐行解释的方式执行,将每条字节码文件中的内容“翻译”为对应平台的本地机器指令执行。JIT (Just In Time Compiler)编译器。

2023-05-29 18:46:53 600

原创 JVM学习(十一):对象的实例化内存布局与访问定位

意思是所有用过的内存在一边,空闲的内存在另外一边,中间放着一个指针作为分界点的指示器,分配内存就仅仅是把指针向空闲那边挪动一段与对象大小相等的距离罢了。将对象的所属类(即类的元数据信息)、对象的HashCode和对象的GC信息、锁信息等数据存储在对象的对象头中。意思是虚拟机维护了一个列表,记录上哪些内存块是可用的,再分配的时候从列表中找到一块足够大的空间划分给对象实例,并更新列表上的内容。实现:通过栈上的reference指向堆中的句柄池中的指针,再由指针指向对象实例和方法区中的类元数据。

2023-05-17 20:22:10 644

原创 JVM学习(七):运行时数据区(精讲)

JVM中的程序计数寄存器(Program counter Register)中, Register的命名源于CPU的寄存器,寄存器存储指令相关的现场信息。CPU只有把数据装载到寄存器才能够运行。这里并非是广义上所指的物理寄存器,或许将其翻译为PC计数器(或指令计数器)会更加贴切(也称为程序钩子),并且也不容易引起一些不必要的误会。JVM中的PC寄存器是对物理PC寄存器的一种抽象模拟。

2023-05-09 20:29:53 633

原创 JVM学习(十):方法区

对栈不熟悉的同学可以参考我的文章:JVM学习(八):虚拟机栈(字节码程度深入剖析)_玉面大蛟龙的博客-CSDN博客 对堆不熟悉的同学可以参考我的文章:JVM学习(九):堆_玉面大蛟龙的博客-CSDN博客 方法区、堆和栈的关系如图: 《Java虚拟机规范》中明确说明:"尽管所有的方法区在逻辑上是属于堆的一部分,但一些简单的实现可能不会选择去进行垃圾收集或者进行压缩。”但对于HotSpotJVM而言,方法区还有一个别名叫做Non-H

2023-05-09 20:13:16 537

原创 JVM学习(九):堆(万字剖析)

Java虚拟机规范》中对Java堆的描述是:所有的对象实例以及数组都应当在运行时分配在堆上(The heap is the run-time data area from which memory for all class instances and arrays is allocated )。《Java虚拟机规范》规定,堆可以处于物理上不连续的内存空间中,但在逻辑上它应该被视为连续的。在方法结束后,堆中的对象不会马上被移除,仅仅在垃圾收集的时候才会被移除(因为垃圾收集的时候才会去扫描垃圾)。

2023-05-01 18:13:18 1136

原创 JVM学习(八):虚拟机栈(字节码程度深入剖析)

由于跨平台性的设计,Java的指令都是根据栈来设计的。不同平台CPU架构不同,所以不能设计为基于寄存器的。 基于栈设计的优点是跨平台,指令集小,编译器容易实现;缺点是性能下降,实现同样的功能需要更多的指令。 有不少Java开发人员一提到Java内存结构,就会非常粗粒度地将JVM中的内存区理解为仅存Java堆(heap) 和 Java栈(stack),这是不正确的。 栈是运行时的单位,而堆是存储的单位。 即:栈解决程序的运行问题,即程序如何执行,或者说

2023-04-25 21:13:02 1023

原创 面试常问:Java中实例变量和局部变量的区别

— 类变量: static修饰。在linking的prepare阶段:给类变量默认赋值;然后在initial阶段:给类变量显式赋值,即静态代码块赋值。—— 实例变量:随着对象的创建,会在堆空间中分配实例变量空间,并进行默认赋值。生命周期与类对象相同。:包括方法形参、方法局部变量、代码块内局部变量。:在使用前,都经历过默认初始化赋值。必须要进行显式赋值!

2023-04-21 21:10:57 186

原创 JVM学习(六):类加载子系统

类加载器子系统负责从文件系统或者网络中加载class文件,class文件在文件开头有特定的文件标识。ClassLoader只负责class文件的加载,至于它是否可以运行,则由ExecutionEngine决定。加载的类信息存放于一块称为方法区的内存空间。除了类的信息外,方法区中还会存放运行时常量池信息,可能还包括字符串字面量和数字常量(这部分常量信息是Class文件中常量池部分的内存映射)

2023-04-18 21:15:11 557

原创 设计模式学习(十三):Chain of Responsibility责任链模式

先用一句话来概括:Chain of Responsibility模式就是。我们首先看看什么是推卸责任。假设现在我们要去公司领取资料。首先我们向公司前台打听要去哪里领取资料,她告诉我们应该去“营业窗口”。然后等我们到了“营业窗口”后,又被告知应该去“售后部门”。等我们好不容易赶到了“售后部门”,又被告知应该去“资料中心”,因此最后我们又不得不赶往“资料中心"。像这样,在找到合适的办事人之前,我们被不断地踢给一个又一个人,这就是“推卸责任”。

2023-04-16 14:10:18 253

原创 Spring原理学习(六):Spring实现动态代理时对jdk和cglib的选择

spring当中不需要我们直接去用jdk或者cglib,它提供了ProxyFactory来方便地创建代理,那么他如何选择代理方法呢?我打算通过AOP中的切面来讲解这一部分。

2023-04-14 15:53:19 925

原创 Spring原理学习(五):一篇讲清楚动态代理(jdk和cglib)的使用、原理和源码

在下面的模拟中,我们的代理目标是Target类,他实现了Foo接口。在main方法中,我们模拟jdk实现动态代理的方法,来模拟实现AOP代理增强。需要注意的一点是:jdk只能针对接口代理。运行结果:需要注意:代理对象Proxy 和 代理目标Target是兄弟关系,他们都实现了Foo接口。所以,目标类Target也可以是final类型,这点与cglib实现的动态代理不同。

2023-04-13 21:29:49 2156

原创 Spring原理学习(四):Scope的介绍及其失效解决方案

虽然上述四种方法各不相同,但理念基本相同,都是延迟其他scope bean的获取。他们都是不直接获取多例,而是在中间加一个对象,通过这个对象等到运行时再去获取多例bean更推荐使用BeanFactory 或 ApplicationContext,因为更加简洁,且不像代理一样会造成一定的性能损耗。

2023-04-08 17:06:39 1174

原创 Spring原理学习(三):BeanFactory后处理器原理解析与模拟实现

我们已经简单介绍了 BeanFactory后处理器 的作用,今天我们先再来再次体验一下。先准备一个主启动类:然后准备一个bean,上面加了@Configuration和 @Bean 注解;并且加上了@ComponentScan 注解,应该能扫描到加有@Component注解的Bean2。所以config容器里应该有5个bean:config本身、扫描到的bean2、自己管理的三个(bean2、sqlSessionFactory、druidDataSource)。

2023-04-07 00:13:00 344

原创 Spring原理学习(二):Bean的生命周期和Bean后处理器

倘若是为了面试,请背下来下面这段:spring的bean的生命周期主要是创建bean的过程,一个bean的生命周期主要是4个步骤:实例化、属性注入、初始化、销毁。

2023-04-04 22:44:57 736

原创 Spring原理学习(一):BeanFactory和ApplicationContext的原理和实现

BeanFactory是一个比较基础的类,他本身并没有特别多的功能,这些事情它不会不会主动调用BeanFactory后处理器不会主动添加Bean后处理器不会主动初始化单例不会解析#{}、${}等。

2023-04-03 21:11:59 1408

原创 Netty学习(八):TCP的粘包拆包与解决方案

TCP是面向连接的,面向流的,提供高可靠性服务。收发两端(客户端和服务器端)都要有一一成对的socket,因此,发送端为了将多个发给接收端的包,更有效的发给对方,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包。这样做虽然提高了效率,但是接收端就难于分辨出完整的数据包了,因为面向流的通信是无消息保护边界的。由于TCP无消息保护边界,需要在接收端处理消息边界问题,这也就是我们所说的粘包、拆包问题。

2023-03-17 11:49:49 1291

原创 Netty学习(七):心跳检测机制

所谓心跳, 即在TCP长连接中, 客户端和服务器之间定期发送的一种特殊的数据包, 通知对方自己还在线, 以确保TCP连接的有效性.心跳机制主要是客户端和服务端长时间连接时,客户端需要定时发送心跳包来保证自己是存活的,否则一个连接长时间没有作用就会浪费服务端的资源。

2023-03-13 15:09:16 4036

原创 Netty学习(六):netty核心模块组件

Channel也提供异步的网络VO操作(如建立连接,读写,绑定端口),异步调用意味着任何IO调用都将立即返回,并且不保证在调用结束时所请求的IO操作已完成,调用立即返回一个ChannelFuture实例,通过注册监听器到ChannelFuture 上,可以VO操作成功、失败或取消时回调通知调用方。入站事件和出站事件在一个双向链表中,入站事件会从链表head往后传递到最后一个入站的 handler,出站事件会从链表tail往前传递到最前一个出站的handler,两种类型的 handler互不干扰。

2023-03-12 15:17:42 338

原创 Netty学习(五):异步模型

异步的概念和同步相对。当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的组件在完成后,通过状态、通知和回调来通知调用者。Netty中的IO操作是异步的,包括 Bind、Write、Connect 等操作会简单的返回一个ChannelFuture。调用者并不能立刻获得结果,而是通过Future-Listener 机制,用户可以方便的主动获取或者通过通知机制获得IO操作结果Netty 的异步模型是建立在 future 和 calback 的之上的。callback 就是回调。

2023-03-08 00:40:43 260

原创 Netty学习(四):TaskQueue中Task的三种典型使用场景

在前文Netty学习(三):Netty线程模型和代码示例中我们学习了netty的线程模型。其中,NIOEventLoop中有两个很重要的部分,一个是Selector,一个是TaskQueue。今天我们要来介绍TaskQueue。我们知道,Pipeline中的一些重量级任务,会放入TaskQueue中异步处理,那么TaskQueue是如何处理这些Task的呢?@Override//比如这里我们有一个非常耗时长的业务-> 异步执行 -> 提交该channel 对应的。

2023-03-06 21:07:26 174

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除