自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 理解线程池原理--手写一个线程池

阻塞队列的实现其实就是根据生产者消费者模型来实现的,这里使用了双向链表Deque实现,遵循队列的FIFO原则,下面我们模拟了一个线程安全的阻塞队列。

2023-02-22 14:51:12 228 1

原创 Spring循环依赖问题--内部是如何解决的?

二级缓存中保存的是一个A的半成品对象,但是A的代理对象还没有生成(A对象才执行到半路就去创建B对象了),我们在对B对象中的A属性进行注入的时候,只能从二级缓存中获取到这个普通的A对象,而并非A的代理对象。如果是这样,那么在进行创建A对象的操作过程中,就需要提前执行它的后置处理器获取其代理对象(也就是在创建完实之后,就去获取它的代理对象),然后再去注入其属性,创建B对象的流程。A对象完成属性的注入,再去执行后置处理器生成代理对象时,就不需要带去做别的操作了,直接从二级缓存中拿刚刚的那个代理对象即可;

2022-10-07 11:58:26 287

原创 结合源码查看Spring容器以及Bean的初始化流程

从上面代码中可以看到,这里创建了一个XmlBeanDefinitionReader对象来加载bean definitions,不同的定义bean的方式会创建出不同的BeanDefinitionReader对象去读取bean definitions,这个也很好理解,比如我们可能不是用的xml的方式来配置定义bean的,而是使用properties配置文件,这个时候,你用XmlBeanDefinitionReader还能读取bean definition吗?

2022-10-05 11:56:23 595

原创 设计模式之适配器模式

将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。来自百度百科。什么意思呢?有一个三孔插座,但是你的电脑只支持两孔插座来充电,这个时候你就需要一个电源适配器来使电脑能够在这个三孔插座上充电。适配器模式属于结构型模式。在软件工程中,适配器模式是一种软件设计模式可以允许将一个已存在的类接口用作另一个接口。它通常用于使现有类与其他类一起工作,而无需修改它们的源代码。类适配器模式对象适配器模式。

2022-10-03 13:33:34 279

原创 SpringBoot的自动配置原理

在了解了上述的原理之后,你想自己写一个starter实现自动配置就会变得非常非常简单。创建一个springboot项目:my-auto-config-boot-starter,并且添加一个基本依赖即可< dependency > < groupId > org.springframework.boot < artifactId > spring-boot-starter

2022-10-02 21:18:52 765

原创 ThreadLocal的内存泄露问题

在上述所说的问题中,即使ThreadLocalMap中存在key为null的Entry,但是该Entry的value值并不会因为GC而被回收(value存本身就存着一个强引用的对象),所以就导致了该对象不会被回收掉而出现了内存泄露。假设如果存储的强引用,我们断开ThreadLocal Reference —> ThreadLocal的引用,会发现key强引用了ThreadLocal,导致该对象永远无法被GC。学习的过程中想到了一个问题,弱引用会不会导致运行过程中GC清除key,导致找不到对应的value?

2022-10-01 16:47:21 4415

原创 JVM类加载过程

比如说,我们在程序中访问一个越界的数组、将一个对象转型为一个它并未实现的类或者我们恶意的去修改这个二进程字节码文件等,这些情况都会在验证阶段被发现。当有多个线程去同时初始化一个类的时候,会使用锁来确保初始化过程中的线程安全问题,当某一个线程初始化很慢的时候,后面的线程就会阻塞等待其初始化完毕。在之前的几个阶段中,几乎都是由虚拟机来完成的,而在初始化阶段,才真正去执行类中的程序代码(也就是字节码)。在准备阶段,只是对一些static对象赋一个默认值,而在初始化阶段,才真正的对这些变量赋上其实际的值。

2022-09-26 14:24:03 307

原创 从字节码角度彻底搞懂i++、++i操作

因为所以的运算操作都是再我们的操作数栈中完成的,而++操作都是直接再局部变量表中进行的,所以load、iinc的执行顺序的不同,就导致了i++和++i的的差异。注意,这里直接在局部变量表中做的自增操作,而我们操作数栈中的数值没有变化,还是3,上述的两步操作也就是i++的操作,先进行load操作,再innc自增。低于short最大大小的数值会直接存放在方法区中,超过short最大大小的数值会被存放到运行时常量池中,如上图所示。上述两步对应的就是++i的步骤,再进行iinc操作,再load进操作数栈。

2022-09-25 16:27:57 351

原创 RabbitMQ如何确保消息不丢失 基于SpringBoot项目解决方式

解决:开启手动ack模式,确保我们在处理完该消息后,手动ack告诉队列,这条消息处理完了,你可以删除了,否则如果出现故障导致该消息并没有被处理,那么还会保留在队列中,不会被丢失。还有一种情况,也就是broker接收到消息了,但是在交换机向队列投递消息的过程中,由于某种原因,消息未能抵达队列,造成的消息丢失。这种情况是在接收者接收到队列中的消息之后,因为某种情况导致该消息并没有被处理到,但是在队列中已经将该消息删除了,导致了消息丢失。注意,在版本较低的RabbitMq中,该消息会一直被重新投递到队列中。

2022-09-22 14:01:47 1105

原创 redis的持久化机制

RDB是一种在指定的间隔时间内将内存中的数据集写入磁盘的一种持久化机制,也就是我们通常所说的快照Snapshot,在恢复文件时,将快照文件直接读取到内存中。redis默认使用的就是RDB持久化机制。将redis中每一个写操作已日志的形式记录到一个.aof文件中(只记录写,不记录读),只许追加文件,而不许改写文件,redis在启动时,会读取该文件恢复数据,换句话说,也就是将日志文件记录的操作在执行一遍。

2022-09-21 13:49:58 638

原创 MySQL索引

InnoDBInnoDB使用的是聚簇索引,在叶子节点存储行数据,如果查询条件为where id = 1这种根据主键查询,则会根据相关的算法找到叶子节点存储的对应的行数据;如果检索条件为where name=“zhangsan”,name是一个单列索引,那么会先查找到辅助索引的叶子节点,找到其存储的对应行数据的主键,然后再拿着这个主键,去主键索引中找到改行数据;聚簇索引默认是主键。

2022-09-17 21:37:32 917

原创 SpringBoot整合RabbitMQ【详细步骤】

注意,这里如果在代码无误的情况下,你并没有在页面发现新创建的交换机和队列,不要着急,继续下面的步骤,这是因为在第一次创建时,要进行一次消息的发送和监听,这些交换机和队列才会被创建在页面中展示。测试一下,发送两条routing-key为book.clicked的消息,该消息会被交换机转发到我们创建的延迟队列book.add.view.delay.queue中。我们可以通过上述方法的参数1直接获得接收的消息体,如果我们发送的消息是一个User类型的对象,那么这里的参数也可以直接写User user接收。

2022-09-10 10:24:58 1423

原创 使用@Autowired注解获取对象为null的几种情况

主要原因就是因为该类继承了一个第三方框架,在执行的过程中,它是被人家框架内部创建实例然后去调用的,这就导致了可能在内部new过这个对象了,所以就导致了@Component对这个类根本不起作用。该类继承了一个WebCrawler,其实就是一个第三方框架,在我执行某个功能的时候,这些被重写的方法就会被其内部自动调用。在该类中使用@Autowired注入对象,就会看到注入的对象为null,尽管这些对象已经在Spring容器中存在了。这是我遇到的情况,当一个对象使用过关键new时,它是不能被Spring所管理的。

2022-09-07 20:08:26 19602 3

原创 【解决】This branch has conflicts that must be resolved git合并代码冲突问题

标识去mark resolution,然后切换到我们自己的分支下,也就是代码需要提交到哪个分支下,这里我是开发环境,所以执行。也就是在合并代码时,发现代码冲突而导致合并不了分支。合并完成后,将我们的代码push到dev分支上即可。并且还会给你相应的提示,告诉你哪个地方出现了冲突。在修改完冲突之后,首先执行。

2022-09-05 23:09:49 3080 1

原创 分代回收算法之新生代垃圾回收流程

三个区域,并且它们的内存比例为8:1:1,比如一个10MB的新生代,会给Eden区分配2MB,两个survivor各分配1MB,但其实供我们使用的内存大小只有9MB,因为其中一个survivor区(survivor to)只是用来协助我们做复制操作的,它不被用来存放对象,看完下面的例子,你会明白。之后的每一次Eden区内存不够放,都按上述的操作来进行垃圾回收,如果在垃圾回收之后,发现还是不够放,那就将整个新生代的对象都放到老年代中,再清空它。就比如,在我们上述例子中,存入12MB大小的对象。

2022-09-04 21:09:15 1651

原创 JVM四种垃圾回收算法

标记-整理算法的第一步也是先对垃圾对象进行标记,和标记-清除法一样,但是下一步并不是将标记的垃圾对象直接进行清除,而是将存活的对象收集到一片连续的区域,也就是将它们都靠在一起,然后在清除标记的垃圾对象。因为新生代中存放的对象大多数都是存活时间很小的,也就是说存活下来的对象很少(98%都会被垃圾回收),所以在复制移动的时候不需要对大量的对象进行操作。在当前的商业虚拟机中都是采用这个方法来进行垃圾回收的,它是根据对象的存活周期去划分不同的内存区域,比如,在JVM中,将堆分为新生代和老年代。

2022-09-04 16:35:49 270

原创 源码分析HashMap中put方法的执行流程

- 调用put方法存放元素,首先先判断当前table数组是否为空,如果为空,则先去初始化这个数组;- 计算出当前存放元素的key的hashcode值,在根据这个hashcode值计算出准备存放到数组的哪个索引下;- 如果当前索引下没有元素,则直接将该元素放到这个索引下;- 如果当前索引存在元素,则进行比较索引下的元素和存入元素是否相同(通过key和hashcode比较);相同则覆盖,不相同则追加到链表或红黑树中。

2022-09-02 21:14:00 406

原创 源码分析LinkedList底层实现

141:创建Node类型的对象l指向我们的last对象,此时的last不再是null了,因为我们前面执行了一次。178:这里判断next此时不为null,所以会执行else语句,将next的prev置为null;144:指向到if判断时,此时l已经不为null了,所以去指向else语句,268:创建一个Node对象f,将first指向的节点对象赋值给它;174:创建一个Node对象next,将它指向f.next节点;可以看到,在remove方法中,主要执行了。,将l节点的next指向newNode;...

2022-08-31 17:58:20 427

原创 源码分析ArrayList的扩容机制

ArrayList的扩容机制,当我们在执行add操作时,发现当前集合容量大小不够了,会扩容到原容量的1.5倍,也就是增加原容量的0.5倍大小,比如大小为10,扩容后为15。

2022-08-31 12:47:45 1603 1

原创 总结了一下StringTable/StringPool以及intern方法一些相关的问题,通俗易懂

分析:new StringBuilder("计算机").append("软件").toString(),先new StringBuilder("计算机"),此时创建两个对象分别在堆和串池中,.append("软件")拼接堆中字符串,现在堆中也就如下图所示,然后将"软件"也放到串池中,注意,再说一遍.toString()不往串池中放东西!此时b引用指向堆中对象。String internB = b.intern(),将b存入串池中,首页先判断串池是否有"计算机软件"字符串对象,发现没有,这........

2022-08-26 23:47:50 531

原创 好用的后端参数校验注解@Validated

在实际写项目的过程中,相信大家对一些表单字段的校验并不陌生,比如?一个前端的登录注册表单,你可能需要对用户名密码的长度进行限制或者对邮箱以及手机号码进行正则校验等。但是大家都知道,仅仅依靠前端进行参数的判断是绝对不行的,市面上的很多请求工具postman这些都是直接绕过前端发送请求的。

2022-08-25 16:13:07 1777

原创 设计模式之工厂模式

这种方式在实际中还是会经常被用到的,它是有一定的好处的,想象一下,当有多个CoffeeStore出现时,或者举个例子,出现了一个DessertStore甜品店,它也需要点咖啡的功能,如果没有工厂,我们还需要在DessertStore中去写一大堆的if else代码去创建咖啡,不如将创建咖啡的工作完全交给一个工厂类,这样一来,不管出现多少个这种店,需要咖啡对象我们直接从工厂从拿就可以了。的方式来创建其实例,有效的解除了原工厂模式中工厂类和其对应的产品对象的耦合。,比如上述案例中,咖啡工厂就只能去生产咖啡。

2022-08-20 12:18:35 176

原创 设计模式之单例模式

这种方式虽然实现了懒加载的功能,但是线程不安全,体现在哪里?在多线程的场景中,不可避免的会有多个线程同时去调用`getExample` 方法,并且在第一个线程并没有执行完`new Example01()`,后面的线程进来判断`if (example01 == null) ---> true`,这样就导致了`example01 = new Example01()`这行代码被多个线程多次执行。...

2022-08-18 16:58:27 282

原创 六大设计原则之依赖反转(依赖倒置)

在面向对象编程领域中,依赖反转原则(Dependency inversion principle,DIP)是指一种特定的解耦(传统的依赖关系创建在高层次上,而具体的策略设置则应用在低层次的模块上)形式,使得高层次的模块不依赖于低层次的模块的实现细节,依赖关系被颠倒(反转),从而使得低层次模块依赖于高层次模块的需求抽象。大概就是说,高层模块不应该去依赖低层模块,这种现象会使得程序的耦合度非常高,而该设计原则,就是为了解决这种耦合关系的。......

2022-08-17 16:06:48 889

原创 【解决】分析SpringSecurity访问请求权限不足AccessDeniedException问题

> 该方法中首先调用了`this.obtainSecurityMetadataSource().getAttributes(object)`方法,通过当前请求路径获取到**访问该请求所需要的权限**(object是上一步调用传过来的参数,封装了我们请求路径的一些信息)。.........

2022-08-13 10:52:47 6164 1

原创 Spring中@Bean注解的作用以及如何使用

想象一下如果我们需要使用外部引入的lib中的组件时怎么办?使用`@Component`注解标注到别人的源码上面?显然这是不现实的,这个时候`@Bean`就可以发挥其优势了。

2022-08-12 17:12:11 5650 3

原创 前后端分离整合阿里云OSS图片上传功能

用户访问服务器,上传图片的操作由服务器完成。缺点- 大量请求访问服务器会造成很大的压力;- 在微服务中,必须要有一个统一固定的地方来存放文件资源,否则在多模块的微服务中,不能保证文件的正确性、一致性。......

2022-08-09 10:25:58 1364

原创 两步实现Mybatis-puls分页功能

这里注意,如果你的mybatis-plus版本比较低,使用如下配置,在高版本的SpringBoot中, 会提示这种写法已过时。除了查询的数据,其他的分页参数信息也可以直接从Page对象中获取。

2022-08-07 22:11:49 826

原创 【解决】访问网关gateway报错,“status“:503,“error“: “Service Unavailable“

nacos兼容feign,feign集成ribbon,默认实现负载均衡;或许是nacos不兼容springcloud gateway自带的ribbon。发现请求能够顺利进入网关,并且配置文件无误,都能够正确读取到,虽然这种有点麻烦,也是我的一种思路吧。期间也考虑过会不会是nacos版本的问题,尝试过换版本,也没有用。...

2022-08-06 22:12:48 8309 2

原创 SpringSecurity+JWT实现认证及授权详细步骤

1. 实现**UserDetailsService**对象中的`loadUserByUsername`方法,根据用户名查询用户信息以及权限信息;2. 自定义controller登录接口;3. 自定义service层登录逻辑,调用`loadUserByUsername`获取用户信息并且校验密码,如果认证成功则生成一个jwt返回,将用户信息存入**SecurityContextHolder**上下文;4. 自定义**JwtAuthenticationTokenFilter**过滤器,获取请........

2022-08-03 16:25:22 1140 4

原创 Java多线程--线程池的参数详解及运行流程

1. 初始化线程池,准备好core数量的核心线程,准备接受任务;2. 新的任务进来,分配给core中空闲线程; 1)core满了,后面进来的任务就会进入到阻塞队列中;当有空闲的core时,就会去阻塞队列中获取; 2)当阻塞队列也满了,此时就会直接创建新的线程,但是线程池总线程数不能超过max;maxSize=20,workQueen=50,有100并发量进来怎么分配的?核心线程大小,也就是一初始化线程池就已经存在里面的线程实例,不管是否处于空闲的状态,一直都会处于线程池里面;...

2022-07-29 09:39:10 734

原创 Java多线程--CompletableFuture异步编排

举一个形象的例子:在一个方法中实现了A、B、C三个功能,假设每个功能的执行所需要的时间分别为(5s,10s,15s),在没有异步编排之前,进入方法依次执行 A功能—>B功能—>C功能,执行方法完毕,用时30s。当我们在方法中引入异步编排,给A、B、C每个功能都分配一个不同的线程执行,这样的情况下,最快15s这个方法就可以执行完毕,这就是所谓的异步。.........

2022-07-28 09:26:10 903

原创 【解决】Feign远程调用丢失请求头问题

在写项目的过程中,使用OpenFeign进行远程调用服务时,获取不到原请求头中携带的cookie信息,也就是Feign远程调用丢失请求头问题。....

2022-07-26 16:50:41 1555

原创 如何使用gitee整合第三方登录网页

创建对应的controller方法,通过刚刚得到的code参数获取一个。点击同意授权,在我们授权登录成功自己的账号后,会跳转到我们之前指定的。一个code只能获取一次accesstoken。会返回一个包含gitee用户个人信息的响应体。如果能看到该页面,说明你第一步配置成功了。.........

2022-07-21 14:28:16 679 3

原创 动态代理的一些简单的总结

快速入门动态代理,学完动态代理的一些自我简单的总结

2022-03-09 11:35:17 200

空空如也

空空如也

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

TA关注的人

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