- 博客(42)
- 收藏
- 关注
原创 AQS源码学习
java.util.concurrent包中的大多数同步器实现都是围绕着共同的基础行为,比如等待队列、条件队列、独占获取、共享获取等,而这些行为的抽象就是基于AbstractQueuedSynchronizer(简称AQS)实现的,AQS是一个抽象同步框架,可以用来实现一个依赖状态的同步器。JDK中提供的大多数的同步器如Lock, Latch, Barrier等,都是基于AQS框架来实现的。AQS具备的特性:1、阻塞等待队列2、共享/独占3、公平/非公平4、可重入5、允许中断。
2024-12-19 17:31:55
1027
原创 深入理解CAS
当有多个线程对一个原子类进行操作的时候,某个线程在短时间内将原子类的值A修改为B,又马上将其修改为A,此时其他线程不感知,还是会修改成功。// 阻塞1s// Thread1通过CAS修改value值为3} else {");// Thread2通过CAS修改value值为2// Thread2通过CAS修改value值为1Thread1不清楚Thread2对value的操作,误以为value=1没有修改过。
2024-12-16 21:51:54
935
原创 RocketMq源码-broker(五)
RocketMQ 主要存储的文件包括Commitlog 文件、ConsumeQueue 文件、IndexFile。RocketMQ 将所有主题的消息存储在同一文件,确保消息发送时顺序写文件,尽最大的能力确保消息发送的高性能与高吞吐量。但由于一般的消息中间件是基于消息主题的订阅机制,这样便给按照消息主题检索消息带来了极大的不便。
2024-12-08 20:29:49
1088
原创 RocketMq源码-Consumer(四)
创建DefaultMQPushConsumer并指定namesrvAddr,然后订阅要消费的主题,并且注册监听器回调函数,然后执行start方法启动消费者。
2024-12-08 00:17:10
1293
原创 RocketMq源码-Producer(三)
DefaultMQProducer设置了NamesrvAddr地址,需要从nameserver获取broker信息。
2024-12-07 15:56:23
1281
原创 RocketMq源码-NameServer(二)
RocketMQ 主要的功能集中在NameServer、rocketmq-broker、rocketmq-remoting、rocketmq-store 4 个模块。
2024-12-06 23:08:27
886
原创 RocketMq(一)
以下我们将总结下Rocket 的整体运转。1. NameServer 先启动2. Broker 启动时向NameServer 注册3. 生产者在发送某个主题的消息之前先从NamerServer 获取Broker 服务器地址列表(有可能是集群),然后根据负载均衡算法从列表中选择一台Broker 进行消息发送。
2024-11-26 21:34:41
1492
1
原创 Netty学习总结
1、虽然JAVA NIO 框架提供了多路复用IO 的支持,但是并没有提供上层“信息格式”的良好封装。例如前两者并没有提供针对Protocol Buffer、JSON 这些信息格式的封装,但是Netty 框架提供了这些数据格式封装(基于责任链模式的编码和解码功能);
2024-11-26 19:38:46
1223
原创 BIO/NIO
NIO 库是在JDK 1.4 中引入的。NIO 弥补了原来的BIO 的不足,它在标准Java 代码中提供了高速的、面向块的I/O。NIO被称为no-blocking io 或者new io都说得通。SelectionKey是一个抽象类,表示selectableChannel在Selector中注册的标识.每个Channel向Selector注册时,都将会创建一个SelectionKey。SelectionKey将Channel与Selector建立了关系,并维护了channel事件。
2024-11-25 22:28:40
809
原创 Linux之epoll原理理解
当某一进程调用epoll_create方法时,Linux内核会创建一个eventpoll结构体,在内核cache里建了个红黑树用于存储以后epoll_ctl传来的socket外,还会再建立一个rdllist双向链表,用于存储准备就绪的事件,当epoll_wait调用时,仅仅观察这个rdllist双向链表里有没有数据即可。有数据就返回,没有数据就sleep,等到timeout时间到后即使链表没数据也返回。
2024-11-25 20:50:30
1237
原创 Dubbo源码解析-超时处理机制(十)
那对于未超时的请求, 在DefaultFuture#received方法中会调用到t.cancel()方法将创建出来的TimeoutCheckTask任务放入到cancelledTimeouts队列中,意思就是不需要对这些任务进行超时检测了,那么worker线程内部处理后也就不会执行到任务的notifyTimeout方法了。然后执行DefaultFuture#receive方法,这里会将放入到FUTURES中的future移除,这些方法都执行完之后会将改请求对应的channel从CHANNELS中移除。
2024-11-25 14:02:52
605
原创 Dubbo源码解析-Dubbo的线程模型(九)
那么问题就出现在AllChannelHandler,前面已经说了AllDispatcher策略就是所有消息都派发到线程池,包括请求,响应,连接事件,断开事件,心跳等。那么当服务端线程池打满之后,此时又再次来了一个请求,此时依然会提交给线程池执行,那么了解线程池原理的就清楚线程池任务满了之后会执行拒绝策略抛出RejectedExecutionException异常,此时就会进入到received的catch方法中去,然后就又再次抛出ExecutionException异常。
2024-11-24 18:59:53
990
原创 Dubbo源码解析-服务订阅与发现(八)
这里要强调一下,在Dubbo 中,URL 是整个服务发布和调用流程的串联信息,它包含了服务的基本信息(服务名、服务方法、版本、分组),注册中心配置,应用配置等等信息,还包括在dubbo 的消费端发挥作用的各种组件信息如:filter、loadbalance、cluster 等等。方法动作很好理解,register 方法就是将url 写入注册中心,subscribe 则将监听器注册到url 上,当服务url 有变化时,则触发监听器的notify 方法,重新生成invoker。
2024-11-24 15:41:24
863
原创 Dubbo源码解析-服务调用(七)
服务在订阅过程中,把notify 过来的urls 都转成了invoker,不知道大家是否还记得前面的rpc 过程,protocol也是在服务端和消费端各连接子一个invoker,如下图:这张图主要展示rpc 主流程,消费端想要远程调用时,他是调用invoker#invoke方法;服务端收到网络请求时,也是直接触发invoker#invoke 方法。
2024-11-22 22:17:46
1360
原创 Dubbo源码解析-服务引入(六)
服务消费方需要用@DubboReference注解来引入Dubbo服务,应用在启动过程中,进行完服务导出之后,就会进行服务引入,属性的类型就是一个Dubbo服务接口,而服务引入最终要做到的就是给这个属性赋值一个接口代理对象。
2024-11-22 00:24:27
1216
原创 Dubbo源码解析-服务注册(五)
之前的服务配置信息是直接从注册中心就可以获取到的,就是服务URL后面,但是现在不行了,现在需要从服务提供者的元数据服务获取,在应用启动过程中会进行服务导出和服务引入,然后就会暴露一个应用元数据服务,其实这个应用元数据服务就是一个Dubbo服务(Dubbo框架内置的,自己实现的),消费者可以调用这个服务来获取某个应用中所提供的所有Dubbo服务以及服务配置信息,这样就能知道服务的配置信息了。这样带来的好处就是,注册中心存储的数据变少了,注册中心中数据的变化频率变小了(那服务的配置如果发生了改变怎么办呢?
2024-11-19 22:41:12
1518
原创 Dubbo源码解析-服务导出(四)
当我们在某个接口的实现类上加上@DubboService后,就表示定义了一个Dubbo服务,应用启动时Dubbo只要扫描到了@DubboService,就会解析对应的类,得到服务相关的配置信息,比如:1. 服务的类型,也就是接口,接口名就是服务名2. 服务的具体实现类,也就是当前类3. 服务的version、timeout等信息,就是@DubboService中所定义的各种配置。
2024-11-15 22:20:25
1159
原创 Dubbo源码解析(三)
Dubbo的使用可以不依赖Spring,但是生产环境中Dubbo都是整合到Spring中一起使用,所以本章就解析Dubbo整合Spring的启动流程。
2024-11-14 17:21:58
1141
原创 Dubbo源码解析(二)
要使用Java SPI,需要遵循如下约定:1、当服务提供者提供了接口的一种具体实现后,在jar 包的META-INF/services 目录下创建一个以“接口全限定名”为命名的文件,内容为实现类的全限定名;2、接口实现类所在的jar包放在主程序的classpath 中;3、主程序通过java.util.ServiceLoder 动态装载实现模块,它通过扫描META-INF/services 目录下的配置文件找到实现类的全限定名,把类加载到JVM;
2024-11-10 21:29:29
977
原创 Dubbo源码解析(一)
在分布式服务架构下,各个服务间的相互rpc 调用会越来越复杂。最终形成网状结构,此时服务的治理极为关键。Dubbo 是一个带有服务治理功能的RPC 框架,提供了一套较为完整的服务治理方案,其底层直接实现了rpc 调用的全过程,并尽力做事rpc 远程对使用者透明。简单的说,Dubbo 就是个服务调用的框架,如果没有分布式的需求,其实是不需要用的,只有在分布式的时候,才有使用Dubbo 这样的分布式服务框架的需求,并且本质上是个服务调用的东西。
2024-11-10 15:59:57
1107
原创 SpringBoot源码解析(三)
前面两章内容已经详细解释了springboot的核心原理与启动流程,本章通过手写模拟实现一个SpringBoot,让大家能以非常简单的方式就能知道SpringBoot大概是如何工作的,作为对上两章内容的一个巩固。
2024-11-08 23:58:10
843
原创 SpringBoot源码解析(二)
从源码我们看到,springboot 的启动就是核心就是主要完成了两件事,一个是spring容器的启动调用了refresh 核心方法;一个是tomcat 的启动,new 出了一个内置的tomcat。
2024-11-08 22:25:17
1097
原创 SpringBoot源码解析(一)
当公司里面需要把一些共用的api 封装成jar 包的时候,就可以尝试自定义启动器来做。自定义启动器用到的就是springboot中的SPI 原理,springboot 会去加载META-INF/spring.factories 配置文件,并加载EnableAutoConfiguration 为key的所有类。利用这一点,我们定义一个工程也会有这个文件。1、定义启动器核心工程,工程结构如下spring.factories 配置内容被springboot SPI 加载的类。
2024-11-04 23:01:38
1635
原创 springmvc请求源码流程解析(二)
它会收集方法上面的@RequestMapping注解,把注解里面的配置信息封装到类里面,该类就是RequestMappingInfo类,并且跟类上面的@RequestMapping注解封装类RequestMappingInfo 合并,比如类上面是/common,方法上面是/queryUser。然后循环参数列表,一个个参数来处理,这里是一个典型的策略模式的运用,根据参数获取一个处理该参数的类,把参数一个个处理完成后,放到一个参数数组中了Object[] args。
2024-10-28 01:08:53
1121
原创 springmvc源码流程解析(一)
SPI 也被称为服务接口扩展,(Service Provider Interface) 直译服务提供商接口, 不要被这个名字唬到了, 其实很好理解的一个东西: 就是根据Servlet厂商(服务提供商)提供要求的一个接口, 在固定的目录 (META-INF/services)放上以接口全类名 为命名的文件, 文件中放入接口的实现的 全类名,该类由我们自己实现,按照这种约定的方式(即SPI规范),服务提供商会 调用文件中实现类的方法, 从而完成扩展。但是这些Bean又是从哪来的呢?3. 方便子容器的切换。
2024-10-24 01:30:01
1566
原创 Spring事务底层源码解析(二)
同理,执行完insertTransactionOne方法之后,继续执行insertTransactionTwo方法,流程跟insertTransactionOne相同,当这两个方法执行完毕的时候,那么就又回到了testTransaction1方法,此时他的newTransaction为true,那么就会执行doCommit方法将事务进行提交。如果传播属性是PROPAGATION_REQUIRED,此时b方法这个属性应该为false,就表名方法b没有开启新事务,复用a方法的事务,最终提交由a方法提交。
2024-10-22 17:50:29
1283
原创 Spring事务底层源码解析(一)
我们在看了jdbc 代码以后可以清楚的知道,事务就是由connection 对象控制的,所以 connection 对象是和事务是绑定的,然后用户请求过来时又需要数据库连接来执行sql 语句, 所以用户请求线程又是跟connection 是绑定的。再看下核心的advice,生成后的代理对象,在调用方法的时候最终会先执行到TransactionInterceptor的invoke方法,然后再invokeWithinTransaction方法里面完成了事务的开启,原始方法的调用,事物的提交和回滚等。
2024-10-21 23:29:54
1249
原创 FactoryBean接口的原理与使用场景
扫描完成后,Spring就会基于BeanDefinition去创建Bean了,相当于每个Mapper对应一个 FactoryBean, 在MapperFactoryBean中的getObject方法中,调用了getSqlSession()去得到一个sqlSession 对象,然后根据对应的Mapper接口生成一个Mapper接口代理对象,这个代理对象就成为 Spring容器中的Bean。经过FactoryBean在以上三个框架中的使用,发现FactoryBean在框架中的经常使用就是生成复杂的代理对象。
2024-10-20 17:32:51
722
原创 spring注解解析与configurationClassPostProcessor(2)
AnnotationMetadata就是该配置类上面所有的注解元信息,注解上面的属性等;6. 如果配置类上存在@ComponentScan注解,那么则解析该注解,进行扫描,扫描得到一系列的 BeanDefinition对象,然后判断这些BeanDefinition是不是也是配置类BeanDefinition(只要存 在@Component注解就是配置类,所以基本上扫描出来的都是配置类),如果是则继续解析该 配置类,(也有递归),并且会生成对应的ConfigurationClass。
2024-10-19 20:02:11
1112
原创 spring注解解析与configurationClassPostProcessor(1)
在进入到这个方法之前,我们先梳理清楚BeanDefinitionRegistryPostProcessor(也就是BeanFactoryPostProcessor的子类)与beanPostProcessor的区别,其实看名字就知道前者是对BeanDefinition的处理,即将java类转换为BeanDefinition的时候起作用,而beanPostProcessor是在从BeanDefinition到bean,即实例化到初始化过程中起作用,不要搞混了。可想而知接下来,就会对MyApp上的注解进行解析。
2024-10-17 23:21:51
1024
原创 spring中xml的解析与beanDefinition封装(1)
然后进入到ComponentScanBeanDefinitionParser的parse方法可以看到,这里先是取出<componet-scan>标签的包路径,然后新创建一个ClassPathBeanDefinitionScanner,执行doScan(basePackages)方法去将bean解析为beanDefinition,然后注册到BeanDefinitionRegistry中。最后,上面是说的通过扫描得到BeanDefinition对象,我们还可以通过直接定义BeanDefinition,或。
2024-10-16 22:45:37
785
原创 spring循环依赖解析(2)
可以点进去getEarlyBeanReference,可以看到这里是一个beanPostProcessor的应用,熟悉AbstractAutoProxyCreator这个类的都知道,这个是支持AOP的关键类,也就是动态代理的入口,这个时候就判断我们的bean是否需要代理,如果需要就会把这个bean放入到earlyProxyReferences,并执行wrapIfNecessary这个方法生成代理对象,此时放入到二级缓存中的A就是代理对象,这里后面还会继续详细讲解,我们先把循环依赖的流程看完。
2024-10-16 13:29:20
1106
原创 spring循环依赖解析(1)
那么这个时候就会先去一级缓存singletonObjects中去寻找,如果为null,那么这个时候就会继续判断isSingletonCurrentlyInCreation(beanName),意思就是这个bean是否在创建中,如果正在创建中就从二级缓存中earlySingletonObjects中去获取,如果再没有就去三级缓存也就是singletonFactory中去查找,此时如果在三级缓存中获取到,则将获取到的bean放入到二级缓存,并且将该bean从三级缓存移除;方法的依赖注 入类似这里就不再赘述。
2024-10-15 22:57:30
723
原创 SPRING的AOP源码解析
找到拦截当前bean 的切面 从收集到的所有切面中,每一个切面都会有pointCut 来进行模块匹配,其实这个过程就 是一个匹配过程,看看pointCut 表达式中的内容是否包含了当前bean,如果包含了,那么这 个bean 就有切面,就会生成代理。这是一个BeanPostProcessor 接口的运用,initializeBean 方法我们都知道是一个 bean 实例化完成后做的操作,而这个代理实例生成也是在bean 实例化完成后做的操作,其核心代码如下。直到数组链中全部调用。
2024-10-15 20:12:12
916
原创 AutowiredAnnotationBeanPostProcessor与CommonAnnotationBeanPostProcessor解析
在bean的创建过程中,会执行到这个收集注解的方法,这里面会调用到AutowiredAnnotationBeanPostProcessor类跟CommonAnnotationBeanPostProcessor类的方法,此时跟这两个类相关的注解都会在此收集。根据收集到的注解进行反射调 用,循环收集到的metaData 中的list 对象,然后挨个调用里面的InjectedElement 的 inject 方法完成依赖注入。bean属性填充之后,会进行bean的初始化,初始化的过程有四个重要的埋点。
2024-10-15 16:37:06
1100
原创 BeanPostProcessor 接口理解
BeanPostProcessor贯穿bean的生命周期始终,BeanPostProcessor 接口类型实例是针对某种特定功能的埋点,在这个点会根据接口类型 来过滤掉不关注这个点的其他类,只有真正关注的类才会在这个点进行相应的功能实现。2、收集@Resource@Autowired@Value@PostConstruct,@PreDestroy 注解的方法和属性。寻找当前正在实例化的bean中有@Autowired注解的构造函数,如果ctors不为空就说明构造函数上有@Autowired。
2024-10-15 14:49:03
339
原创 Spring的bean的实例化流程以及bean的生命周期
在这个过程中,同时会执行很多的beanPostProcess的执行,BeanPostProcessor 接口类型实例是针对某种特定功能的埋点,在这个点会根据接口类型 来过滤掉不关注这个点的其他类,只有真正关注的类才会在这个点进行相应的功能实现。看源码的时候肯定有很多分支,如果想每行代码都看清楚是不可能的,所以先看最常用的主分支,在这个基础上再去看一些特殊的分支,那么bean实例化的时候最先进到的方法就是getBean,然后再调用到createBean。然后继续把该bean放入到三级缓存中。
2024-10-15 14:05:20
317
原创 BeanFactoryPostProcessor理解
2、postProcessBeanDefinitionRegistry方法执行完后执行postProcessBeanFactory方法,这个方法的核心处理流程在enhanceConfigurationClasses,处理的是@Configuration中的@Bean方法,对这种注解做了代理。Spring执行流程中的一步是invokeBeanFactoryPostProcessors,如下图。
2024-10-15 13:18:21
245
原创 SPRING源码阅读-beanDefinition理解
BeanDefinition 在spring 中贯穿始终,spring 要根据BeanDefinition 对象来实例化bean,只要把解析的标签,扫描的注解类封装成BeanDefinition 对象,spring才能实例化bean。(4)、parent:子类Bean 定义它所引用它的父类Bean。(10)、depends-on(依赖对象):这个Bean 在初始化时依赖的对象,这个对象会在这个Bean 初始。(8)、autowire(自动装配,默认为“default”):它定义了Bean 的自动装载方式。
2024-10-14 21:35:17
416
原创 @Autowired与@Resource的区别
Autowired在获取并注入bean的时候,需要先根据byType获取,如果找不到或者获取到多个bean,则此时根据字段名称byName进行获取;但是@Resource注解如果要注入的bean不存在,则改属性值为null,不会抛错。@Resource在获取并注入bean的时候,是先根据byName,然后根据byType,不过这个注解也能通过参数显示指定通过哪种方式。@Autowired是可以作用在构造器,字段,setter方法上,但是@Resource无法作用在构造器上面。
2024-10-14 14:32:26
203
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人