- 博客(46)
- 收藏
- 关注
原创 spring boot启动源码分析(三)之Environment准备
本篇开始讲启动过程中Environment环境准备,Environment是管理所有配置的实例对象,像application.yml、系统属性、环境变量等配置都可以通过Environment.getProperty(key)获取
2025-01-09 10:34:21
1009
原创 Spring boot源码之EnvironmentPostProcessor
EnvironmentPostProcessor主要是在环境实例Environment准备好后,发布EnvironmentPreparedEvent时,EnvironmentPostProcessorApplicationListener响应该事件,调用各个EnvironmentPostProcessor.postProcessEnvironment对环境实例Environment进行后置处理。EnvironmentPostProcessor配置在spring.factories中,主要涉及。
2025-01-09 10:33:06
884
原创 redis cluster集群安装部署
这里是本地虚拟机演示cluster集群部署,所以直接安装了6个节点,模拟的是3个服务器,每台服务器安装2个redis进程,6个redis组成集群。
2025-01-06 20:46:01
1286
原创 spring-boot启动源码分析(二)之SpringApplicationRunListener
在上一篇《》后,继续看了一个月的Spring boot启动源码,初步把流程看完了,接下来会不断输出总结,以巩固这段时间的学习。同时也希望能帮到同样感兴趣的同学。话不多说,进入正题环境介绍:spring boot版本:2.7.18主要starter:spring-boot-starter-webSpringApplication实例构造后,就开始调用它的run方法,开始启动spring boot。方法如下:本篇主要介绍上图中的4步,SpringApplicationRunListener会重点讲。
2025-01-02 22:12:15
1126
原创 logback之配置文件使用详解
-- 设置是否在启动时触发之前丢弃的事件 -->-- 设置这个appender的neveQueueSize -->-- 添加真实的appender -->-- 保留最近30天的日志文件 -->
2025-01-02 15:39:14
1974
原创 logback之自定义过滤器
if (!} else {} else {} else {= null) {过滤器的过滤方法decide很简单,只是对日志事件的级别进行判断,是否在[minLevel,maxLevel)进行判断,支持[,maxLevel)以及[minLevel,)。几个注意事项:(1)过滤器必须实现Filter接口,这里建议继承AbstractMatcherFilter。
2024-12-31 15:26:32
807
原创 logback日志框架源码分析
在我们使用logback日志框架时,通常都会通过配置logback.xml定制化我们的日志需求。但你是否对loback日志如何加载配置感到好奇?如果没有logback.xml,logback的默认配置又是什么样的?配置文件中定义的appender和logger又是什么关系呢?在这一篇章我们会通过深入logback源码进行分析。
2024-12-31 15:26:17
1757
原创 logback之自定义pattern使用的转换器
首先有这么一个场景:我定义了一个ImpossibleLogger,用于在比较复杂的场景(通常涉及并发),不可能执行的地方进行日志打印,并且单独记录日志。这样如果这个日志文件不为空,说明程序可能偏离我们的设想,需要排查。因为包装了一层,那么如果使用%class %m打印调用类以及方法,那么只会是ImpossibleLogger以及对应的warn,无法实际区分业务调用类。所以我们想实现自己的转换器,把实际的业务调用类打印出来。
2024-12-28 21:14:00
807
原创 logback之pattern详解以及源码分析
d或%date:表示日期,可配置格式化%d{yyyy-MM-dd HH:mm:ss}%r或%relative:也是日期,不过显示的是相对时间,是相对于日志框架加载开始的时间,单位是ms。%level或%le或%p:表示日志级别%t或%thread:表示线程名%lo或%logger或%c(小写c):表示logger的名称,即 LoggerFactory.getLogger传入的名称,如果传入的是class则为类全限定名。%m或%msg或%message:表示日志消息。
2024-12-28 21:11:52
1403
原创 Java Agent的应用
Java Agent是通过 JVM 的 Instrumentation API 实现的一种机制,它允许开发者在运行时修改或监测已加载类的字节码。这一特性为我们提供了非常广泛的应用场景,包括但不限于代码注入性能监控、调试工具和安全检查等。在示例中我们也自定义了转换器,但只是简单的把已存在的类文件保存到本地,如果要实现redefineClasses一样的功能,应该如何做呢?更改方法体主要是在转换器中transform方法中,所以我们需要重写此方法。
2024-12-18 21:05:20
1311
原创 nodepad之正则表达式删除无关键字符串的行
经常遇到需要对日志文件查找关键日志(比如按线程名称)进行问题分析,但日志又太多,比较干扰看关注的日志,所以就想把无关键字的行删除掉,那么该怎么做呢。.*http-nio-8091)就表示不以包含了http-nio-8091的字符串作为开头。http-nio-8091为日志中打印的线程名称,可以自行替换为任何你想匹配的字符串。(1)替换无关键字的所在行,如上图所示,匹配的关键字是http-nio-8091。正则表达式为:^(?.*http-nio-8091).*$匹配空行的正则表达式是:^\s*\n。
2024-12-18 21:04:31
479
原创 spring boot之@Import注解的应用
但因为没有直接导入它两的外围类UserConfiguration这个配置类,所以不能用它的Bean方法获取,而是用对应类获取:下方的两种获取方式,UserInfo可以获取到bean,但ClassInfo不行。然后重写它的registerBeanDefinitions方法逻辑,自行实现bean定义,然后通过注册器进行bean的注册。这样UserConfiguration中定义的Bean就会被加载了,我们直接在调试状态下可以看到使用上下文是可以获取到UserConfiguration中定义的Bean的。
2024-12-09 22:52:57
589
原创 Spring boot集成mybatis
2、map-underscore-to-camel-case:将数据库返回的下划线格式的字段映射到Java对象的驼峰式命名属性,这样可以省去resultMap去定义数据库表字段和实体类的映射关系。1、type-aliases-package:开启包别名,用于mapper.xml简化类型映射,如:配置此项后,type可以只写类名,mybatis会自动去配置包名中找该类。我们以java config的方式配置事务,所以就不在配置文件中配置mybatis开头的配置项了。(二)配置文件中增加数据库相关配置。
2024-12-09 14:15:44
237
原创 oracle之用户的相关操作
5、QUOTA 100M ON MALLTABLESPACE:quota是限制用户在表空间的空间配额,比如MALLTABLESPACE的表空间的存储还有3g,但如果限额100m,那么用户使用了100m之后,就没有空间可存储了,即使表空间还有多余的空间。DEFAULT_TABLESPACE:就是我们设置的用户默认表空间,用户建的表、索引、视图等都存储在此表空间下。用户创建后通常需要额外的给用户授予一些权限(请遵循最小授权原则),请参见本篇章的第6点用户授权部分。(5)用户的锁定与解锁(sys用户)
2024-12-06 14:45:27
580
原创 Oracle之表空间迁移
上面这个sql没试过,因为我先执行了上一条sql语句(不带lob字段)的迁移,结果删除表空间的时候提示还有字段在表空间,才发现clob没有迁移。如果表中有lob字段,上面sql并不能把lob字段一起迁移到新表,因为clob字段会另外单独存储。问题背景:一个数据表随着时间的累积,导致所在表空间占用很高,里面历史数据可以清除,保留近2个月数据即可。如果你也先执行了第一条sql迁移表空间数据,那么可以使用下面这条sql,额外把lob字段迁移到新表空间。(2)将表迁移到新的表空间(表所在用户)
2024-12-06 09:57:25
1062
原创 Postman的使用
(2)x-www-form-urlencoded:对应Content-Type为application/x-www-from-urlencoded,这是post请求默认的格式。数据以键值对进行传输。(4)binary:对应着http请求中的Content-Type:application/octet-stream,只可以上传二进制数据,通常用来上传文件,由于没有键值,所以一次只能上传一个文件。(3)raw:对应Content-Type=application/json。post的body格式有4种。
2024-12-05 20:08:28
531
原创 Postman自定义脚本Pre-request-script以及Test
(二)我们经常会有多套环境,prod,test,dev,如果每次环境切换都要改每个请求的ip和端口,那太麻烦了。如果我们不用自定义脚本,可能得先执行请求A,然后手动复制响应结果给请求B的参数。pm是postman内置的对象,可以通过它获取请求参数,响应结果等信息,也可以设置请求参数、设置环境变量、全局变量等。(2)然后再第二个请求中的Pre-request Script中写脚本获取响应结果,并设置到参数中。这两个都是我们进行自定义script脚本的地方,分别是在请求执行的前后运行。
2024-12-05 20:03:57
727
原创 设计模式之模板方法
其中end是通用逻辑,代表通用不变的部分;start提供了默认的实现,但可被子类重写覆盖,代表相对不变的部分。而step1和step2则是需要子类提供,代表可变的业务逻辑。注意:这里可变、不变的顺序不是固定的,根据实际业务场景而定,也有可能是中间不变,开始和结尾部分是变化的。而在onClose中也提供了默认实现,但运行子类自行决定是否需要做些什么,这个其实是预留的钩子,运行子类自行实现它想在关闭时做的任何事,虽然父类也不清楚这些事是啥。模板方法的思想就在于,父类将骨架定好,子类根据需要自定义变化的部分。
2024-12-04 21:16:41
567
原创 linux环境中后台运行java程序
可以看到providerlog.log有记录程序的部分启动日志,我们的应用日志通常会使用日志框架归档到指定的日志目录,等日志框架加载后,应用程序就会将日志记录到指定日志文件。但将进程信息输出到一个日志文件依然很有必要,因为有些没有被程序代码捕获的异常,最终会输出到控制台,如果没有输出到日志文件,那么这部分异常记录将丢失。如果只是用&,那么会话关闭后,进程也将结束。在生产环境,我们通常需要让java进程后台运行,并且即使会话关闭,进程也依然存在。(1)nohup:是让进程持续运行,即使会话关闭也不影响。
2024-12-04 20:24:44
592
原创 设计模式之单例
而懒汉模式是线程不安全的,想象一下多个线程同时在单例还没实例化时进入,那么Objects.isNull(instance)判断为true,从而都会创建实例然后返回,那么有可能返回的是不同的单例。那么在单例还没初始化完成时,其他线程进入获取单例时,引用对象就不是空,而提前获取到还没初始化完成的单例引用,就可能会导致后面的业务逻辑出错。第一次校验是基于性能考虑,避免每次都进行加锁,因为只有还没实例化时这个短暂且特殊的场景是需要加锁的,大部分时候都是直接返回实例就行。所以单例对象是等要用的时候再进行实例化的。
2024-12-01 21:20:15
914
原创 java之enclosing class
可以看到除了顶层类的enclosingClass是null以外,其他的都是UserInfo。所以我们现在应该就能猜到getEnclosingClass是获取它的外围类,Enclosing Class确实也是外围类的意思。一直没注意这个,于是好好了解了一下。这里在延伸一下,如果在嵌套类中再定义一个内部类,那么这个内部类的外围类是嵌套类还是顶层类呢?上面定义了五种类型的类,并打印它的enclosingClass。(3)内部类(非静态的嵌套类)(4)局部类(方法中定义的类)下面通过一段代码来详细说明。
2024-12-01 11:05:39
201
原创 浅谈volatile
而volatile则会保证变量只要修改就会马上同步到主内存中,并且线程读取变量时也是会先从主内存中刷新变量值,以此来保证了变量的可见性。这得从虚拟机的内存模型说起,这里直接引用《深入理解java虚拟机》书中原话:JAVA内存模型规定了所有的变量都存储在主内存中,每条线程还有自己的工作内存,线程的工作内存保存了被该线程使用的变量的主内存副本,线程对变量的所有操作(读取、赋值)都必须在工作内存中进行,而不是直接读写主内存中的数据。上面这个例子执行后,如果是原子性的,那么count的值应该是50000。
2024-11-30 21:29:54
699
原创 Spring boot之BeanDefinition介绍
Bean的创建是一个比较复杂的过程,它并不像我们创建对象一样只是直接new一下就行,虽然有些bean确实就是New一下。在这个过程中,BeanDefinition作为bean定义,存储了bean创建所需要的信息,一个后置处理器也是通过修改BeanDefinition实现对bean的扩展和修改。翻译一下:BeanDefinition是一个接口,它描述了一个具有属性值、构造参数值以及其他更多的信息,这些信息有具体的实现提供。factoryBeanName:bean的工厂名称,用于创建bean实例。
2024-11-30 14:24:32
655
原创 线程池execute异常信息消失
重点来了:它从Worker中获取firstTask,即我们实际的Runnable,然后调用它的run方法。这里用了两层try catch,第一层捕获了异常,然后继续抛出,同时在finally将任务和异常都传给了afterExecute方法。我们可以看到,我们的命令被传入Worker中,然后启动的线程是Worker中thread。我们启用了一个线程池,然后在任务重抛出运行时异常,模拟业务报错抛异常场景。我们自定义一个线程池,然后重写afterExecute方法,在里面将异常输出,这样就解决了^_^!
2024-11-29 23:00:58
368
原创 线程池拒绝策略之DiscardPolicy在submit时的陷阱
任务取消后,所以我们在Future.get时会抛出CancellationException,所以我们需要增加对此异常的处理。我们定义一个最大线程数为5的线程池,先提交5个任务,然后再提交submit,那么submit的那个任务就一定会被拒绝。答案是自定义拒绝策略,然后在拒绝时,把任务取消掉,这里是针对任务可以丢失的场景,如果任务不能丢失,也可以进行持久化,之后再重新拉取任务执行。我们在开始把线程名打印到日志里了,因为是在@PostConstruct中写的测试代码,所以是主线程执行。
2024-11-29 21:32:07
575
原创 JVM之Synthetic
这里编译器在内部类生成了一个TestInnerClass的引用对象this$0,因为是编译器自动合成的,所以标记了ACC_SYNTHETIC。所以这也就解释了为什么内部类创建需要外部类对象创建了,如果外部类对象还没有生成,怎么传给内部类的构造方法呢?而下面是内部类的构造方法,可以看到它传入了外部类的实例对象,之后把它赋值给this$0。aload_0默认是实例方法第一个参数是this,即内部类自己的引用。而我们内部类能调用外部类的方法,也正是通过外部类的实例对象调用的。
2024-11-28 20:37:23
495
原创 spring-boot之 自定义上下文初始化器ApplicationContextInitializer及源码分析
通过遍历我们在SpringApplication构造方法中获取的初始化器,依次调用初始化器的initialize方法,这样初始化器的执行就完成了。到了这里,大家可能就会疑惑:这里初始化器都是从spring.factories中定义的才会执行,那我们通过context.initializer.classes应用变量配置的初始化器怎么执行呢。这里获取的初始化器只有在spring.factories定义的才能获取到,也就是我们的第一种配置方式。(2)构造器只是实例化了初始化器,但并没有直接调用执行初始化方法。
2024-11-28 09:59:58
945
原创 spring-boot启动源码分析(一)之SpringApplication实例构造
spring.factory是spring boot的核心,里面定义了spring boot需要使用的接口,以及对应的实现类。loadSpringFactories(classLoaderToUse)返回的是类加载器加载所有的spring.fatories数据,返回的是Map,key是工厂接口,value是对应实现类列表,所以通过factoryTypeName就可以获得对应的实现类,这里只是类的全限定名。然后对工厂实例进行排序,因为有些实例执行是有顺序要求的。
2024-11-27 21:50:43
1129
原创 spring-boot自定义ApplicationListener及源码分析
上面代码可以看到代理类也监听了所有的事件,然后在ApplicationEnvironmentPreparedEvent事件时才初次响应,并且通过getListeners获取所有代理的ApplicationListeners,然后它自己实现了一个事件广播器,然后把获取的ApplicationListeners通过到addApplicationListener加入到广播器中,最后进行事件的广播转发。我们可以看到,是通过我们配置的context.listener.classes获得类名,然后通过反射实例化返回。
2024-11-26 22:17:21
513
原创 spring boot自定义banner
图标banner是通过配置“spring.banner.image.location”自定义的,文字则和配置spring.banner.location有关。然后在配置文件yml中定义“spring.banner.image.location”和"spring.banner.location"配置。获取自定义的图标banner和文字banner,如果没有自定义则使用spring boot 默认的banner。入口:在SpringApplication.run方法中会调用printBanner打印。
2024-11-23 10:05:04
213
原创 元注解@Target,@Retention,@Documented,@Inherited,@Repeatable
(1)@Target:定义注解作用范围,值是ElementType的枚举数组,可以是作用于类,方法,字段,参数等。然后定义一个UserInfoChildren类继承UserInfo,使用TestHello注解修饰UserInfo,但不修饰UserInfoChildren。(3)@Dumented:使用此注解定义的注解在其他类使用时,生成javadoc时会被一起记录。RetentionPolicy.CLASS:class文件会留存,但不会在虚拟机运行时感知,即在运行时无法通过反射获取注解信息。
2024-11-21 14:57:47
629
原创 RetentionPolicy.CLASS和RetentionPolicy.RUNTIME的区别
比如lombok的注解基本都是RetentionPolicy.SOURCE,用于在编译成class文件时动态生成代码,在class文件看不到对应注解存在。所以我们在运行时是无法获取对应注解的信息的,那么它有什么用的。根据类加载的过程,加载需要经过加载,校验,准备,解析,初始化,使用,卸载,这七个步骤,在加载的时候就是把class文件加载到虚拟机,那么这时候虚拟机是能从class文件中感知到注解的存在的,那么就可以在连接阶段(校验,准备,解析)阶段根据信息进行一些操作,个人猜测大概率是给虚拟机底层使用的。
2024-11-19 19:35:13
594
原创 idea 安装checkStyle插件
(4)选择规则模版,File->settings->Other Settings->Checkstyle。插件提供了两个绑定的sun和google编码格式的模板,可以选择。(6)运行检查代码,Rules可以随时切换上面三个规则模板,没选的话默认就是setting设置的,点击运行蓝色图标就可对当前类进行检查。(5)选择自定义规则模板,点击+号填入描述,导入xml文件。我用的是从网上找的huawei规则模板。(2)搜索CheckStyle-IDEA,点击Install安装。然后选择对应自定义规则模板就行。
2024-11-19 16:23:23
627
原创 linux端口访问不了问题
再次查询,返回yes,端口开启。执行 firewall-cmd --permanent --add-port=8848/tcp 开启端口。在本地主机用telnet ip 8848查看是否端口可通,发现无法连接,说明应该是虚拟机端口没开放。问题背景:在虚拟机中安装了nacos,但本地主机访问不了,主机已经和虚拟机能ping通。输入命令: firewall-cmd --query-port=8848/tcp。再次查询还是返回no,那么需要执行防火墙命令重载。结果返回是no,说明端口确实未开启。
2024-11-18 17:10:33
1080
1
原创 linux 基础常用操作命令
3.cp test.txt /etc/test/test.bk.txt 将文件test.txt复制一份到/etc/test目录下,新文件名为test.bk.txt。命令模式下输入:wq,可以保存并退出,w代表保存,q代表退出,两者可以单独使用,即可以只保存不退出,或者不保存直接退出,wq!Mv /etc/test.txt /test 将 /etc/test.txt文件剪切到/test目录下。Vi进入为命令模式,按i进入插入模式。8.Vi /etc/test.txt 编辑/etc/test.txt文件。
2024-11-18 16:04:47
700
原创 Could not retrieve mirrorlist
打开/etc/yum.repos.d/CentOS-Base.repo,安装下载就是通过读取里面的镜像地址进行安装的。可以看到里面提示“如果mirrorlist不能访问,可以用baseurl”,但改了baseurl后虽然能访问,但会报文件找不到。访问baseurl的域名,确实能访问,但已经提示不再支持与维护。在主机上访问尝试访问,确实也是网络不通的。再次安装lrzsz就可以了。
2024-11-18 14:38:08
857
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人