AQin1012
少年有他的山海
展开
-
启动正常但无法Debug?解决ERROR: transport library not found: dt_socket
项目启动类的jre环境与项目设置里jdk环境配置未统一。项目启动时正常,但是Debug就报错,如下图。① 项目设置里jdk环境配置。② 启动类的jre环境。原创 2024-05-24 12:57:53 · 577 阅读 · 0 评论 -
【保姆级】Protobuf详解及入门指南
Protobuf(Protocol Buffers)协议😉 Protobuf 是一种由 Google 开发的二进制序列化格式和相关的技术,它用于高效地序列化和反序列化结构化数据,通常用于网络通信、数据存储等场景。原创 2024-03-11 16:45:22 · 26683 阅读 · 0 评论 -
【自制小工具】如何给你的图片添加自定义水印(附完整代码)?
这段代码用到了Graphics2D,Graphics2D是Java中用于绘图的工具类,是Graphics类的扩展,可以绘制形状、图像、文本等各种二维内容,上面的代码的逻辑是先搜索你电脑里都安装了哪些字体,然后依次用这些字体在特定的位置给特定地址的图片加上特定的文字水印~当然这只是其中一部分字体,,,我也是今天才发现我电脑里居然装了那么多字体 ==这是一篇关于怎么尽可能的用尽你电脑里的所有字体给你的图片加水印。搞定撒花*★,°*:.☆( ̄▽ ̄)/$:*.°★*。就是在原有的基础上添加了透明度和循环。原创 2023-12-31 20:36:51 · 599 阅读 · 4 评论 -
【JUC】Java并发编程从挖坑到入土全解(4-一文讲通LockSupport与线程中断->长图预警)
首先,一个线程不应该由其他线程强制中断或停止,而是应该由线程自己自行停止,自己来决定自己的命运(所以,Thread的stop()、suspend()、resume()都已经废弃了)其次,在Java中没有办法立即停止一条线程,然而停止线程又显得那么重要(比如需要取消一个耗时/错误操作)。因此,Java提供了一种用于停止线程的协商机制——中断,也即中断标识协商机制。中断只是一种协作协商机制,Java没有给中断增加任何语法,中断的过程完成完全要求程序员自己实现。原创 2023-10-10 15:46:15 · 456 阅读 · 11 评论 -
【JUC】Java并发编程从挖坑到入土全解(3-线程池源码分析)
在web开发中,服务器会为每一个请求分配一个线程来处理,如果每次请求都要创建一个线程的话,实现起来虽然简单,但是存在一个问题:如果开发的请求数量非常多,但每个线程执行的时间很短,这样就会频繁的创建和销毁线程,如此会大大降低系统的效率,很有可能出现服务器在创建和销毁线程上花费的时间和消耗的系统资源比实际处理的用户请求的时间和资源还多。于是,线程池应运而生,线程池满足了一个线程执行完一个任务不会被销毁,而是可以继续执行其他任务的目的。原创 2023-09-28 11:34:39 · 364 阅读 · 13 评论 -
【JUC】Java并发编程从挖坑到入土全解(2-当我们聊锁时,锁的到底是什么)
当对方法加synchronized关键字时,锁的是当前对象(this),所以即使是多线程只要调用的是同一个对象的synchronized方法,就需要串行执行(案例1和案例2),未被synchronized修饰的普通方法则不受影响(案例3)如果是不同对象则不受影响(案例4),分别在自己的对象上加锁,不会影响到别的对象当在带有“static”的方法上加了synchronized关键字时,锁的是当前类,无论几个对象,都要抢类的这一把锁,因而是否使用同一对象都会串行执行。原创 2023-09-17 18:35:37 · 165 阅读 · 2 评论 -
【JUC】Java并发编程从挖坑到入土全解(1-直达底层源码的线程基础)
JUC全称java.util.concurrent ,是在并发编程中使用的工具包。原创 2023-09-12 18:01:35 · 159 阅读 · 1 评论 -
一篇文章搞定Java中常用集合的排序方法
最近在做算法题的时候,发现排序在大部分题中都不可或缺,今天心血来潮,总结下Java中集合排序常用的方法,基本覆盖了大部分的排序场景(特别是自定义比较器,太好用叻( ̄▽ ̄)/)文中提到的自然顺序排序,对于可比较大小的数据类型,一般按照从小到大的顺序,无法比较大小的,一般指按字典序升序排列。原创 2023-06-07 17:57:22 · 5690 阅读 · 10 评论 -
【JMM】并发编程Bug的源头——可见性/有序性/原子性问题
synchronized内置锁是一种对象锁,锁的是对象,而非引用,作用粒度是对象,可以用来实现对临界资源的同步互斥访问,并且可重入。在 Java 早期版本中,synchronized属于重量级锁,效率低下,因为内部对象Monitor(监视器锁)是依赖于底层的操作系统的Mutex Lock实现的,Java 的线程是映射到操作系统的原生线程之上的。如果要挂起或者唤醒一个线程,都需要切换到操作系统的内核态来完成,这个状态切换导致早期的 synchronized 效率较低。原创 2023-05-23 16:31:17 · 930 阅读 · 14 评论 -
【JMM】保证线程间的可见性,还只知道volatile?
volatile保证线程之间的可见性依靠的是内存屏障我们先介绍下volatile在hotspot虚拟机中的实现。原创 2023-05-12 13:56:07 · 965 阅读 · 22 评论 -
【操作系统】从操作系统底层出发,成为更好的程序员
首先,我们从一个问题开始( ̄∇ ̄)/为什么需要程序员?早期的计算机程序是硬件化的,即使用各种门电路组装出一个固定的电路板,这个电路板只能用于执行某个特定的程序,如果需要修改程序功能,就要新组装一个电路板。而一位叫做冯诺依曼的老爷子的出现,提出了一种指令数据化的思想,使得程序和数据一样,可以存储起来,组合调用,至此,程序脱离了电路板的桎梏,成为了可以人为组合的指令集,程序员应运而生。当然,我们需要郑重地介绍下这位冯老爷子,1903年12月28日—1957年2月8日),原名),出生于的籍与的奠基者,在和。原创 2023-05-09 17:56:41 · 872 阅读 · 28 评论 -
【Spring源码】AOP的开端:核心对象创建的准备工作
AOP的核心成员是如何被被加载的?本篇我们主要分析使用xml的逻辑,如果使用注解,增加注解处理类即可(ConfigurationClassPostProcessor)拿之前分析循环的时候举的例子🌰,它的日志切面就是通过xml进行配置的(配置文件📃内容如下,完整测试代码可参考中的示例代码)通过ApplicationContext applicationContext = new ClassPathXmlApplicationContext;启动容器。原创 2023-03-03 14:21:43 · 1296 阅读 · 13 评论 -
【Spring源码】Spring AOP的核心概念
关于什么是AOP,这里还是要简单介绍下AOP,Aspect Oriented Programming,面向切面编程,通过预编译和运行期间提供动态代理的方式实现程序功能的统一维护,使用AOP可以降低各个部分的耦合度,提高代码质量。原创 2023-02-28 13:26:09 · 739 阅读 · 17 评论 -
【保姆级】手把手捋动态代理流程(JDK+Cglib超详细源码分析)
动态代理,通俗点说就是:无需声明式的创建java代理类,而是在运行过程中生成"虚拟"的代理类,被ClassLoader加载。从而避免了静态代理那样需要声明大量的代理类。上面的简介中提到了两个关键的名词:“静态代理”和“动态代理”我们先来看来下两个问题:首先什么是代理呢?它可以看作是对最终调用目标的一个封装,可以通过操作代理对象来调用目标类,这样就可以实现调用者和目标对象的解耦合“静态代理”和“动态代理”又有什么区别呢?原创 2023-02-23 13:33:47 · 233676 阅读 · 15 评论 -
【JVM】关于Arthas官网缺少的那段“-output”
简单理解就是两个处理方式,一个强制输出到终端,另一个指定个文件作为输出文件。下载完成后就可以使用java -jar启动下载好的jar进行测试啦。其实具体操作步骤建议按照官网(中文且详细且最新)(。・ω・。)ノ。但但但是~这里需要提到使用过程中碰到的一个坑坑。输入dashboard,回车显示详情。输入2(选择想要连接的程序号)的时候会出现三行警告。原创 2023-02-18 11:29:36 · 1313 阅读 · 4 评论 -
【Spring源码】23. 执行初始化逻辑:initializeBean()
遍历该工厂创建的bean的BeanPostProcessors,依次调用当前遍历到的BeanPostProcessor的postProcessBeforeInitialization()方法(这个方法会在初始化Bean前进行调用),将当前BeanPostProcessor应用到给定的Bean实例(由于Bean已经填充了属性,返回的可能是原始Bean的包装器)结果是执行到输出行前,代码停在了initializeBean()方法的断点处,点击继续,执行了输出操作,接着就直接结束了,也就是说,我。原创 2023-02-09 11:05:10 · 658 阅读 · 4 评论 -
【保姆级】超超超简单的自定义注解实现@Autowired同款功能
对,构造函数,我们把原先构造函数中添加autowiredAnnotationTypes中的注解类换成了我们自定义的注解类AqinAutowired.class,所以在这次的逻辑中,会将被注解AqinAutowired修饰的字段/方法添加进特定存放的集合。着急想看到效果的同学可以直接无脑copy我贴出的代码,先执行成功开心一下(或者直接往下看我的截的执行结果颅内兴奋下也成( ̄∇ ̄)>),我把分析放在最后,有兴趣自行前往观看(。・ω・。)ノ。1个自定义注解类(AqinAutowired.java)原创 2023-02-08 17:01:34 · 802 阅读 · 8 评论 -
【Spring源码】属性值的解析与赋值:populateBean().applyPropertyValues()
方法一开始判断传入的PropertyValues是否为空,如果为空则直接返回,不为空则继续后面的处理逻辑判断是否有安全管理器并且bw是否为BeanWrapperImpl的实例,如果都为true则切换为安全上下文继续判断传入的pvs是否是MutablePropertyValues的实例是,进行isConverted()的判断,以免进行重复处理,不是,获取pvs的propertyValue对象数组,并且将其转换为列表。原创 2023-02-07 17:12:06 · 492 阅读 · 0 评论 -
【Spring源码】自动注入·类型:autowireByType()详解
进入方法autowireByType()首先获取工厂的自定义类型转换器,如果获取到没有配置自定义类型转换器就使用bw作为类型转换器插播:为什么类型为BeanWrapper的bw可以赋值给类型为TypeConverter的converter?因为BeanWrapper继承了ConfigurablePropertyAccessor,而ConfigurablePropertyAccessor继承了TypeConverter。原创 2023-02-06 17:23:43 · 651 阅读 · 1 评论 -
【Spring源码】自动注入·名称:autowireByName()详解
这里的“简单”值类型需要同时满足三个条件:值类型不为Void.class(Void.class!= type)值类型不为void.class(void.class!= type)满足以下条件任意:这里有两个方法需要介绍下(。・ω・。)ノ。原创 2023-01-31 09:57:15 · 628 阅读 · 1 评论 -
【Spring源码】22. 属性填充populateBean()详解
当needsDepCheck为true时,会进行行依赖检查,判断filteredPds是否为空,如果为空会对其进行赋值,最终通过调用checkDependencies()检查pd的setter()方法需要赋值时,pvs中有没有满足pd需求的属性值可供其赋值。前面介绍过的resolveBeforeInstantiation()这个方法中就有类似的代码(这个方法是应用实例化前的前置处理器,给BeanPostProcessors一个机会来返回代理代替真正的实例)有咩有客官觉得if (!原创 2023-01-30 13:40:55 · 967 阅读 · 1 评论 -
【Spring源码】插播一个创建代理对象的wrapIfNecessary()方法
在文章中,提到过一个方法——wrapIfNecessary(),就是在这个方法中为Bean创建的代理对象,介于篇幅原因,当时并咩有详细🔎分析这个方法,这篇文章我们进去wrapIfNecessary()这个方法中瞅瞅(。・ω・。)ノ。原创 2023-01-29 10:46:25 · 697 阅读 · 0 评论 -
【分析向】没有三级缓存会导致什么?
通过上篇(【实践向】当移除了三级缓存……)的实践,我们得出的结论是:如果不存在代理对象,二级缓存就可以解决循环依赖性的问题,但是当存在代理对象的时候,二级缓存则无法完全解决循环依赖,需要引入三级缓存那么、在没有三级缓存的情况下,引入代理后为什么会报错?由于我们的代码只修改了两处,但前后出现了不同执行结果,所以我们可以将分析重点🔎放在修改的两处代码上(代码与文章【实践向】当移除了三级缓存……中的修改后的代码一致,想动手实践下的可以去瞅下,本文较长,这里就不贴叻)原创 2023-01-28 13:06:06 · 237646 阅读 · 2 评论 -
【实践向】当移除了三级缓存……
上面的实践过程直观的证明了一个我们早就知道的结论(˶‾᷄ ⁻̫ ‾᷅˵):如果不存在代理对象,二级缓存就可以解决循环依赖性的问题,但是当存在代理对象的时候,二级缓存则无法完全解决循环依赖,需要引入三级缓存。原创 2023-01-17 14:19:03 · 859 阅读 · 0 评论 -
【保姆级】手把手Debug循环依赖的整体流程
我们先看一下循环依赖,这样看、或者这样看、一提到循环依赖基本必提三级缓存,本篇又是篇保姆级的Debug教程,详解出现循环依赖Spring处理的全过程,之前也介绍过一些与本篇相关的内容:想瞅瞅三级缓存的庐山真面目可以移步到想了解更多关于三级缓存的相关内容欢迎移步到。原创 2023-01-16 11:22:56 · 240658 阅读 · 10 评论 -
【Spring源码】21. 初探循环依赖
不同的Bean之间的依赖关系形成了一个闭环(比如ABean依赖了BBean,同时BBean又依赖了ABean),我们把这种依赖关系就称为循环依赖一级缓存 -> 二 级缓存 -> 三级缓存就是往三级缓存中放入创建当前对象lambda表达式,方便后续进行回调调用。原创 2023-01-12 13:25:33 · 544 阅读 · 0 评论 -
【Spring源码】CommonAnnotationBeanPostProcessor.postProcessMergedBeanDefinition()详解
CommonAnnotationBeanPostProcessor的postProcessMergedBeanDefinition()中一共包含3个方法,上篇文章我们介绍了的第一个方法,它一个父类调用(如下图),其实就是处理@PostConstruct和@PreDestroy这两个注解的这篇我们继续介绍后面两个方法( ̄∇ ̄)原创 2023-01-11 14:58:03 · 576 阅读 · 2 评论 -
【Spring源码】AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition()详解
像之前介绍CommonAnnotationBeanPostProcessor一样的,我们进入applyMergedBeanDefinitionPostProcessors()方法中的循环中,当遍历的BeanPostProcessor为AutowiredAnnotationBeanPostProcessor时,就开始了我们这篇文章⁄(⁄ ⁄ ⁄ω⁄ ⁄ ⁄)⁄~~~原创 2023-01-11 14:57:35 · 252 阅读 · 0 评论 -
【保姆级】@PostConstruct & @PreDestroy使用示例
感兴趣的同学可以注意下,上面在处理被@PostConstruct和@PreDestroy注解修饰的代码中并没有出现@PostConstruct和@PreDestroy,出现的是InitAnnotationType和DestroyAnnotationType,那么@PostConstruct和@PreDestroy是在哪里被转换为InitAnnotationType和DestroyAnnotationType的?原创 2023-01-10 17:44:48 · 569 阅读 · 0 评论 -
【Spring源码】20. MergedBeanDefinitionPostProcessor修改/合并bean定义
随后进入applyMergedBeanDefinitionPostProcessors()方法applyMergedBeanDefinitionPostProcessors()方法中调用MergedBeanDefinitionPostProcessor后置处理器修改/合并bean定义进入bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName)原创 2023-01-10 17:37:37 · 1159 阅读 · 0 评论 -
【Spring源码】19. 没合适的构造器?找determineCandidateConstructors()!
上篇介绍了instantiateBean()(其实这个方法在后面还会再次被调用)如果在前两篇的内容结束后都还未获取到构造函数,那么则继续向下执行,调用determineConstructorsFromBeanPostProcessors()方法。原创 2023-01-10 16:46:04 · 555 阅读 · 1 评论 -
【填坑向】我可能也就是踩了dockrfile部署jar包(需读取resource目录下的文件)全部的坑吧。。。
没错、这篇还是从读取的文件找不到的问题开始,今天来个终极版( ̄∇ ̄)/一开始我把要读取的文件放在了项目根路径,package就没把它打进去,显然是找不到的,于是我把这个JSON文件移到了resources中此时可以看到,这个文件也打进了target中,这部分可以参考之前的一篇的文章,那里有记录过获取路径失败的原因,这里就不重复赘述叻今天这篇是有新发现!算是填上一篇文章的坑( ̄∇ ̄)/在官网上了解到可以通过解包的方式,来读取jar包中的内容。原创 2023-01-04 15:31:31 · 597 阅读 · 0 评论 -
【填坑向】Linux获取Java程序resource下的文件路径(这次的坑好像没填住……
(˶‾᷄ ⁻̫ ‾᷅˵)痛定思痛,目前得出的结论就是,由于package后要获取的文件变成了jar包里的一份子,因此系统磁盘中找不到一个路径可以直接指向它,但是由于他在jar包中,是可以通过流的方式获取到文件内容的,如果真的非要获取到文件地址,就新建一个文件,把读取到的流写入,在这种情况下,就可以获取到这个新文件的磁盘路径 由于我的文件较大,读取写入新建文件并不合适,而我这边又是需要通过路径来调用第三方库的,因此。感觉貌似可以了,生产环境需要package,先本地打包试下,再调用下试试(b_d)。原创 2022-12-20 15:38:30 · 225610 阅读 · 0 评论 -
【保姆级·创建对象】如何通过factory-method创建对象
这个步骤在createBeanInstance()方法中有使用,我们先来看下这个方法中都干了些啥(。・ω・。)ノ 首先,方法开头确认了beanClass是否被加载(因为只有被加载叻的对象才是可以实例化的)然后,判断当前beanDefinition中是否包含实例供应器,此步骤如果instanceSupplier!=null的话,则会直接通过obtainFromSupplier(instanceSupplier, beanName);方法直接返回一个Bean的包装类BeanWrapper而不会再进行下面的逻辑叻原创 2022-12-06 16:42:08 · 711 阅读 · 0 评论 -
【保姆级·创建对象】如何通过Supplier创建对象
Spring创建对象的主要方式有自定义BeanPostProcessor,生成代理对象InstantiationAwareBeanPostProcessorcreateBean() -> resolveBeforeInstantiation()通过supplier创建对象createBean() -> doCreateBean() -> createBeanInstance() -> obtainFromSupplier()通过FactoryMethod创建对象createBean() -> doCreat原创 2022-12-05 16:44:13 · 581 阅读 · 0 评论 -
【Spring源码】18. factory-method创建对象关键函数详解:instantiateUsingFactoryMethod()
factoryMethod和args的相关判断,如果没解析过,就获取factoryClass的用户定义类型,因为此时factoryClass可能是CGLIB动态代理类型,所以要获取父类的类型。如果为空的话,就要去找出factoryClass的以及父类的所有方法,进一步找出方法修饰符一致且名字跟工厂方法名字相同的且是bean注解的方法,并放入列表里。如果获取到的候选方法只有一个,且传入的参数为空,且没有设置构造方法参数,就进行一系列的相关参数设置,然后返回BeanWrapperImpl对象。原创 2022-11-23 16:26:08 · 602 阅读 · 0 评论 -
【保姆级·创建对象】如何利用resolveBeforeInstantiation()在预处理阶段返回一个Bean的实例对象
本文我们来盘盘prepareMethodOverrides()方法后面的resolveBeaforeInstantiation()的函数,看过之前文章介绍的同学应该有印象,它是应用实例化前的前置处理器,是在正式实例化前的一种预处理方式(即在预处理阶段给BeanPostProcessors们一个机会来返回代理来代替真正的实例)所以如果我们想要进入if的逻辑中,就需要同时满足这两个条件,直接用Spring源码debug是不会进入的,所以我们需要创造条件,让程序进入if的逻辑中。原创 2022-11-15 15:12:34 · 1468 阅读 · 7 评论 -
【Spring源码】自动注入·类型:autowireByType()详解
接下来的逻辑是尝试获取与type匹配的唯一候选bean对象,查找与type匹配的候选bean对象,构建成Map,如果构建的Map对象为空,则继续判断descriptor是否需要注入,如果需要则抛出异常,不需要则返回空表示未找到候选的bean对象。而autowiredBeanName是从集合autowiredBeanNames中依次获取的,而autowiredBeanNames是方法autowireByType()在一开始定义了一个空的集合(下图1处)原创 2022-11-14 14:01:50 · 485 阅读 · 0 评论 -
【Spring源码】自动注入·名称:autowireByName()详解
这里的“简单”值类型需要同时满足三个条件:值类型不为Void.class(Void.class!= type)值类型不为void.class(void.class!= type)满足以下条件任意:这里有两个方法需要介绍下(。・ω・。)ノ。原创 2022-11-11 17:48:50 · 722 阅读 · 0 评论 -
【保姆级】lookup-method标签实践与分析
** * @Description * @Author aqin1012 AQin. * @Date 2022/8/22 10:25 AM * @Version 1.0 */ public abstract class AnimalAction { /** * 获取执行该动作的动物 * * @return */ public abstract Animal getAnimal();本文就是这两种情况的栗子🌰,感兴趣的同学可以跟着一步一步操作,绝对保姆级教程(不愧是俺(˶‾᷄ ⁻̫ ‾᷅˵))原创 2022-11-04 13:24:52 · 955 阅读 · 2 评论