自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 SpringBoot源码(十四):spring三级缓存源码,解决循环依赖

介绍在写springboot项目时,我们对于bean的注入都使用注解的方式进行注入。可以根据field注入,set方法注入还有构造器方法注入。但是我们都写过类似下面的代码:@Servicepublic class Bean1 { @Autowired private Bean2 bean2;}@Servicepublic class Bean2 { @Autowired private Bean1 bean1;}即Bean1和Bean2互相引用,

2021-04-28 10:32:42 2540

原创 SpringBoot源码(十三):spring获取bean的源码

介绍前面一章说了AbstractApplicationContext中的refresh方法中的invokeBeanFactoryPostProcessors。主要是调用BeanFactoryPostProcessor。其中也有获取bean的过程,就是beanFactory.getBean的方法。这一章就说下getBean这个方法。由于spring中获取bean的方法比较复杂,涉及到的流程也非常多,这一章就先说下整个大体的流程。其中的细节会在后面也会慢慢说。源码直接看源码吧 @Overrid

2021-04-23 21:36:37 917 4

原创 SpringBoot源码(十二):refreshContext(二) invokeBeanFactoryPostProcessors

介绍接着说refreshContext中的内容,invokeBeanFactoryPostProcessors方法。这个方法主要就是调用实现spring的BeanFactoryPostProcessor的实现类。源码先来介绍下BeanFactoryPostProcessor接口。public interface BeanFactoryPostProcessor { void postProcessBeanFactory(ConfigurableListableBeanFactory b

2021-04-21 21:49:56 369 1

原创 SpringBoot源码(十一): refreshContext(一)

介绍refreshContext是springBoot启动源码中最复杂的部分了,里面的内容也非常多,将会拆分很多个章节去说。源码refreshContext里面就是调用AbstractApplicationContext的refresh的方法。主要的功能就是注册spring容器里面的bean,以及对bean的处理还有广播等功能。接着看源码吧 public void refresh() throws BeansException, IllegalStateException { sy

2021-04-13 23:33:31 716 1

原创 SpringBoot源码(十): prepareContext

介绍前面一章介绍了创建ApplicationContext,这章将会介绍ApplicationContext的一些处理工作。源码 private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments application

2021-03-25 22:05:23 291 1

原创 SpringBoot源码(九): createApplicationContext

介绍前面一章介绍了启动流程中的打印banner,接下来继续根据springBoot启动的源码分析,createApplicationContext方法。ApplicationContext是spring容器的核心,其实一般我们所说的spring容器,一般也可以说是ApplicationContext,具体点就是ApplicationContext里的DefaultListableBeanFactory,后面在bean的创建时候会详细介绍的,现在就先了解下ApplicationContext的创建,以及在

2021-03-24 23:43:58 622 1

原创 SpringBoot源码(八): 打印banner

介绍接着prepareEnvironment之后继续介绍springBoot启动流程的代码,接下来看看banner的打印。源码 private Banner printBanner(ConfigurableEnvironment environment) { // banner模式,如果为off则不打印 if (this.bannerMode == Banner.Mode.OFF) { return null; } ResourceLoader reso.

2021-03-22 16:27:04 990

原创 SpringBoot源码(七): ConfigFileApplicationListener

介绍configFileApplicationListener是spring中对于配置文件解析的监听器,主要是负责对于配置文件的解析,并且加入到environment中去。源码在上一章中prepareEnvironment方法,会发送广播ApplicationEnvironmentPreparedEvent事件到广播,然后各个监听器接收处理。对于如何设别到监听器就不多解释了,之前也介绍过。别的监听器暂时先不看,先看最重要的configFileApplicationListener。直接看C.

2021-03-21 13:00:28 2240

原创 SpringBoot源码(六): 启动流程:prepareEnvironment

介绍前面介绍了spring对于键值的抽象PropertySource,以及对外提供数据的统一处理接口PropertyResolver。还有对ConfigurableEnvironment的源码解析。接下来继续看springBoot启动流程的源码prepareEnvironment。prepareEnvironment private ConfigurableEnvironment prepareEnvironment( SpringApplicationRunListeners l.

2021-03-11 21:51:57 893

原创 SpringBoot源码(五): ConfigurableEnvironment

介绍Environment是spring中配置文件数据的载体,对外暴露使用的配置文件名称,如:profiles.active,这样我们就可以知道在使用哪个配置文件的信息了。ConfigurableEnvironment继承于Environment,并且ConfigurableEnvironment还继承了ConfigurablePropertyResolver,而ConfigurablePropertyResolver继承于PropertyResolver。对于PropertyResolver上

2021-03-11 15:45:51 9178 2

原创 SpringBoot源码(四): PropertySource以及解析

介绍ConfigurableEnvironment是spring容器中非常重要的角色,它继承Environment,主要负责解析profile的定义,以及解析文件放到map中供spring容器去使用。源码public interface ConfigurableEnvironment extends Environment, ConfigurablePropertyResolver { void setActiveProfiles(String... profiles); vo

2021-03-10 21:26:30 2240

原创 SpringBoot源码(三): ApplicationArguments

介绍继续之前说的从springboot启动去阅读源码在 listeners.starting()之后就到了参数解析了,再次发一下启动的源码; public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; Co.

2021-02-24 20:55:57 933

原创 SpringBoot源码(二): SpringApplicationRunListeners.starting()

介绍上一章介绍了springBoot启动时候,还未运行run方法时的初始化。现在继续介绍run方法的内容。下面就是run方法的所有内容了,接下来会分步去介绍各个类和方法的作用。public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext contex

2021-02-02 23:32:45 1469

原创 SpringBoot源码(一): 启动SpringBoot时的初始化

SpringBoot源码(一)最近自己看了一点springBoot的源码,想要整理一下。供自己学习,顺便看看能不能对有疑惑的小伙伴有帮助。介绍版本:2.0建议新看源码的小伙伴还是先看1.5版本的,和2.x版本的差异不是很大。主要是2.x版本用到了太多的lambda的匿名类特性,以至于逻辑不太容易理解。这里我是先看了1.5的版本,然后又去看了下2.x版本的。这边主要是从springBoot的启动开始分析源码,通过分析整个启动流程,来看看springBoot和spring的源码。..

2021-02-01 21:47:10 1197 2

原创 java8中的lambda接口Consumer,Function,BiConsumer,BiFunction

简介在java8中新增lambda表达式,平时我们用的也比较多,主要用于替代匿名内部类,使代码更加的优雅简洁。最近在看spring源码时,发现内部用到的也非常多。虽然我们大部分用的都是stream,但是其中也涉及到非常多的函数式接口,比如Consumer,Function,BiConsumer,BiFunction等等。所以今天就梳理下java8中的一些函数式接口。函数式接口在说lambda之前,先解释下什么是函数式接口。函数式接口指的是有且只有一个抽象方法。由于java8支持接口实现默认方法,

2021-01-05 17:05:41 1583

原创 java Comparable和Comparator的区别和应用

简介Comparable和Comparator都是接口,一般都用于比较。但是Comparable只有一个compareTo方法。Comparator里面有很多方法,但是都有默认方法(java8接口可以实现默认方法),主要实现compare接口。应用ComparableComparable主要用于同对象之间的比较,因为它的compareTo接口只有一个对象。看下实际的例子。import java.util.Arrays;import java.util.Collections;.

2020-12-16 21:41:39 203

原创 AQS condition的源码实现

介绍说到AQS中的condition,大家基本都用过,主要就是await和signal的方法的使用。使用方式和wait于notify类似,也都是需要获得锁。但是signal不一样的一点是可以指定线程唤醒,虽然执行了也不一定立刻唤醒,但是可以指定想要的线程唤醒。这点就比notify要灵活许多。先举个简单的应用的例子,大家都能看懂。然后说下在AQS中,await和signal的源码是如何实现的。public class TestAwait1 { private final Reentrant

2020-12-09 16:31:14 169

原创 AQS共享锁源码分析

上一篇博客介绍了AQS中的排他锁,现在说一下AQS中的共享锁。源码解析获取锁 public final void acquireShared(int arg) { // 剩余锁的资源是否大于0 if (tryAcquireShared(arg) < 0) doAcquireShared(arg); }private void doAcquireShared(int arg) { // 设置锁.

2020-12-08 23:15:17 289 1

原创 AQS排他锁源码分析

介绍说到java中的锁就会想到synchronized和lock,而说到lock一般就会想到ReentrantLock,而ReentrantLock的底层实现就是依赖于AbstractQueuedSynchronizer,也就是AQS。AQS已经实现了底层的逻辑,对于想要自己实现锁,只需要继承AQS然后维护其state状态就可以了。源码解析状态解析waitStatus状态解析:CANCELLED(1):表示当前结点已取消调度。当timeout或被中断(响应中断的情况下),会触发.

2020-12-02 16:17:37 244

原创 left join on and 和 inner join on and的多条件查询区别

我们都知道 left join 是以左表为基准和其他表进行连接, 返回左表的记录。而inner join是两张表的交集的记录。但是当多条件查询时,会怎样呢?先做个测试:person1表的记录:person2表的记录:先看下left join:可以看到结果 ,即使在and后面加了过滤条件,依然会返回名称是 小丽 的数据。这是因为左连接是以左边表为基准,无论on后面的条件如何,都会返回左表,然后再根据条件来返回右表。 所以当前例子查询不是小丽的时候,返回了左表数据,但是无法.

2020-09-28 17:51:45 3247 2

原创 jdbc的rewriteBatchedStatements参数配置

在做项目开发时候,我们在使用mysql时,底层驱动一般都是jdbc,但是我们在执行批量时候,如果开启rewriteBatchedStatements参数配置时,是无法批量更新的,因为在mysql底层会进行判断jdbc:mysql://localhost:3306/test?characterEncoding=utf8&allowMultiQueries=true&rewriteBatchedStatements=true...

2020-09-25 15:13:02 1141 2

原创 mysql limit优化之延迟关联

最近在做一个数据同步功能,从一个200多万的数据表中进行数据清洗,然后根据逻辑再更新回去。在刚开始做的时候,按照我的分析,应该一个线程去读,然后放到blockingqueue中,多个线程去处理程序就够了。毕竟读并不会很慢,还有索引,只是逻辑处理时候比较慢,因为还要去查别的数据再更新数据。但是最后我发现,越到最后查询越慢,我多线程写已经变成单线程了(因为线程都在空闲,blockingqueue中无数据),然后我才发现原来是到最后读的满了。越到后面limit分页性能和代价越大(100多万时候查询1000

2020-09-18 13:41:37 571

原创 java泛型上界和下界

package test.generic;import java.util.ArrayList;import java.util.List;public class TestEat<T> { private List<T> list1 = new ArrayList<>(); public List<T> push(List<? extends T> list) { for (T t: list) .

2020-08-25 21:50:53 212

原创 查看mysql存储过程和函数

查看存储过程:select * from mysql.proc where db = 'xx' and `type` = 'PROCEDURE'show procedurestatus;查看函数select *from mysql.proc where db = 'xx' and `type` = 'FUNCTION'show function status;

2020-07-28 14:41:02 111

原创 mybatis(三):mybatis自定义分页

由于之前mybatis的版本较低,以至于在自定义分页的时候,只能返回列表,总量还是得自己调用count方法,现在升级了mybatis版本之后,对自定义分页进行改造,让其能返回page,代码如下:pom依赖,mybatis版本在3.1.1 <dependencies> <dependency> <groupId>com.baomidou</groupId> <artif.

2020-07-05 20:09:32 755

原创 mybatis(二):mybatis分页和自定义分页

接mybatis第一章说的mybatis,再写一下mybatis集成分页的情况。mybatis分页首先需要一个分页的插件,代码如下:package test.mybatis.plus.config;import com.baomidou.mybatisplus.plugins.PaginationInterceptor;import org.springframework.context.annotation.Bean;import org.springframework.co.

2020-07-02 23:56:18 531

原创 mybatis(一):springboot集成mybatis-plus

之前一直用的jpa,现在项目上开始用mybaits,今天想搭一个自己玩玩但是过程有点艰辛,特地记录下来。首先引入pom依赖:<dependencies> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus</artifactId> <version

2020-07-01 23:04:48 172

原创 redis根据redis.windows.conf启动命令

redis有时候我们需要自己配置一些参数,比如密码等等,这样我们就需要根据配置文件去启动。这里记录下windows下redis根据conf启动的命令,当你redis.windows.conf配置好之后写一个bat文件,命令用redis-server redis.windows.confredis.windows.conf 跟redis-server是同一个路径,所以不要加绝对路径,如果不在同一路径那就加上路径就可以了...

2020-07-01 09:37:39 2530 3

原创 springcloud(二):zuul网关过滤

zuul的过滤我们需要继承zuul的一个抽象类 ZuulFilter。继承了ZuulFilter这个抽象类之后,我们需要实现它的4个抽象方法:filterType: filter的类型,分为pre,route,post,error。pre是在路由之前执行,route是在路由时候执行,post是在路由完成之后执行,error,是在发生错误时候执行。filterOrder:根据filterType类型,再根据filterOrder的值正序执行。shouldFilter:返回布尔值,判断此过滤器.

2020-06-29 23:31:03 174

原创 zuul:Zuul中RequestContext.setSendZuulResponse记录

一般我们在用zuul写网关的时候,会做一些过滤,但是如果过滤的校验没有通过,我们就不希望zuul转发到后端服务器上了,这样的话我们就可以设置RequestContext.getCurrentContext().setSendZuulResponse(false)这样就不会转发到后端的服务上了,但是如果后面还有filter执行的话,其实还是会执行的,我们只需要重写下shouldFilter这个方法就可以了,这个方法可以控制是否走这个filter。...

2020-06-29 21:30:00 1002 1

原创 多线程:字符串多线程交替输出的多种实现方式

最近看到一道面试题字符串两个线程交替输出,简单写一下做个记录,主要用到的就是wait和notify,初始代码如下:package test.thread.wait;public class Wait3 { private String str1 = "ABCDEFGH"; private String str2 = "abcdef"; private volatile boolean flag = false; public synchronized void

2020-06-18 18:43:27 13620

原创 springcloud(一):记录下搭建Eureka,zuul的使用

我们都知道springcloud架构一般是网关,注册中心,还有一些业务服务,原来都是项目上直接用,今天就把搭建过程写一下,方便自己以后查询。首先搭建一个Eureka的server端 test-eureka:在pom中引入依赖: <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> &lt

2020-06-15 16:30:41 13657

原创 Thread的join方法

Thread中的join方法主要的作用是让jion的线程加入当前线程,等加入的线程执行完之后才会执行当前线程。接下来看个例子:public class TestJoin { public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(() -> { try { Thr

2020-06-11 15:47:10 14647

原创 java synchronized锁升级过程

synchronized在jdk1.6之前,一直都是重量级锁。为什么称之为重量级锁呢,主要是因为锁的资源是通过操作系统去申请,所以比较重量级。在jdk1.6之后,jvm对synchronized进行了升级,对锁的粒度进行了细化,分为无锁,偏向锁,轻量级锁,重量级锁。性能得到了很大的提升。锁升级的过程是怎样的呢?主要一开始是无锁的状态,如果偏向锁未启动,当有其他线程竞争时,会升级为轻量级锁,如果偏向锁启动,则会升级为偏向锁,如果竞争激烈则会从偏向锁升级为重量级锁,如果不激烈则有偏向锁升级为轻量级.

2020-06-10 17:38:31 15492

原创 java锁消除和锁粗化

什么是java锁消除呢?其实这些都是JVM帮我们做的功能,在JVM判断一个锁不会被其他线程使用,就会把锁消除来提高性能。比如下面代码,我们知道StringBuffer的append方法上加入了synchronized关键字,所以是加了锁的,但是JVM知道这个StringBuffer是线程私有的,所以没有其他线程会访问到,所以JVM会取消锁,加快性能。 private void appendString(){ StringBuffer sb = new StringBuffe

2020-06-09 16:37:49 13844

原创 AQS(一): java公平锁和非公平锁的实现

最近在读AQS的源码,想一步一步分析记录下来,接下来阅读源码,看一看ReentrantLock公平锁和非公平锁的实现。 public ReentrantLock() { sync = new NonfairSync(); } public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); }在ReentrantLock的构造

2020-06-09 11:25:36 14313

原创 mysql聚集索引和非聚集索引区别

聚集索引是索引叶子节点上存的是数据,非聚集索引的叶子节点存的是数据的指针。聚集索引是物理上连续存在,而非聚集索引是逻辑上的连续,物理存储不连续。聚集索引每张表只能有一个,非聚集索引可以有多个。mysql的innodb引擎必须要有主键,因为数据存放在聚集索引上,即使不设置主键,mysql也会设置一个默认主键,需要去存放数据。其他索引也就是非聚集索引或者叫二级索引(辅助索引)存放的是主键的数据,从而根据主键的查找到数据。myisam引擎可以不需要主键,因为引擎会单独存储数据,索引上存放的是指向数

2020-06-03 11:09:45 14645

原创 java中volatile关键字保证可见性有序性

我们知道java并发编程主要会有可见性,原子性,有序性几个问题。volatile可以保证可见性和有序性,但是无法保证原子性。有序性:编译器会根据自认为的排序对代码进行指令重排,指令重排不会对单线程造成影响,但是可能会导致多线程时候运行错误。可见性:可行性是指对线程的操作对其他线程可见。volatile关键字可以禁止指令重排,所以可以保证了有序性。有序性也通常是指的happen-before原则。程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作 锁定规则

2020-06-01 17:20:46 14771

原创 @Transactional注解失效的原因

最近项目上遇到@Transactional注解失效,排查问题发现是由于没有@Transactional注解的方法去调用了有@Transactional的方法,导致@Transactional注解失效。顺带一提还有当@Transactional放在非public方法时,也会导致@Transactional注解失效。...

2020-06-01 15:22:37 14553

原创 手写一个spring starter

由于springboot内部有 SpringFactoriesLoader这个类,这个类在springboot启动时,会进行加载,然后会读取 META-INF/spring.factories 里文件,从而实现自动装配bean,所以现在手写一个starter也同样使用这个方式。其中SpringFactoriesLoader部分源码展示:private static Map<String, List<String>> loadSpringFactories(@Nullable

2020-05-26 16:51:47 13778

空空如也

空空如也

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

TA关注的人

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