<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[点滴记录]]></title><description><![CDATA[https://github.com/zhchenme]]></description><link>https://blog.youkuaiyun.com/codejas</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; codejas]]></copyright><item><title><![CDATA[代码整洁之道]]></title><link>https://blog.youkuaiyun.com/codejas/article/details/117331219</link><guid>https://blog.youkuaiyun.com/codejas/article/details/117331219</guid><author>codejas</author><pubDate>Thu, 27 May 2021 16:10:42 +0800</pubDate><description><![CDATA[幕布链接：https://share.mubu.com/doc/2qVEGDxoift
命名

函数


]]></description><category></category></item><item><title><![CDATA[工作上的一些思考]]></title><link>https://blog.youkuaiyun.com/codejas/article/details/116587851</link><guid>https://blog.youkuaiyun.com/codejas/article/details/116587851</guid><author>codejas</author><pubDate>Mon, 10 May 2021 10:06:39 +0800</pubDate><description><![CDATA[思来想去觉得还是要记录些什么，从一开始工作到现在多多少少还是有点想法。这次主要分享下工作中自己的一些思考与收获。
19 年 10 月份加入了现在这家公司，当时公司里并没有 Java 技术栈，所以我们团队需要从零搭建 Java 分布式体系架构。得益于上家公司的技术体系，我们任务模块划分的很清晰，分工也比较明确。
因为团队人手问题，每个人都负责不同的业务模块，任务较重。当时自己的情况是刚从实习转正没多久，对于这种大型项目没有什么经验，心理上的压力比较大。现在看来心理压力大的原因主要在于做项目时没有一个完整的规划]]></description><category></category></item><item><title><![CDATA[业务总结004:检验项目时间轮实践与库存实现方案]]></title><link>https://blog.youkuaiyun.com/codejas/article/details/113879534</link><guid>https://blog.youkuaiyun.com/codejas/article/details/113879534</guid><author>codejas</author><pubDate>Sat, 20 Feb 2021 11:21:07 +0800</pubDate><description><![CDATA[2020 年底公司和阿里健康合作了一个检验项目，由我司提供检验项目(商品)、采样点(商户)、库存等底层数据，与阿里健康开发对接后在支付宝平台进行线上预售，开发流程其中也包括订单数据的交互。
项目开发期间踩了比较多的坑，做了很多优化，其中也包含一些有意思的技术实现方案。
一、时间轮实践
某些业务场景下，我们需要频繁调用阿里健康接口，项目第一个版本上线后，发现有部分请求触发阿里健康接口流控告警，原因是他们提供的接口在一定的时间内只允许 N 次接口调用。针对这个问题，想到了以下几种实现方式：

sleep 同步调]]></description><category></category></item><item><title><![CDATA[Netty时间轮调度原理分析，再不了解你就out啦]]></title><link>https://blog.youkuaiyun.com/codejas/article/details/111677974</link><guid>https://blog.youkuaiyun.com/codejas/article/details/111677974</guid><author>codejas</author><pubDate>Fri, 25 Dec 2020 14:18:56 +0800</pubDate><description><![CDATA[一、时间轮介绍
之前公司内部搭建的延迟队列服务有用到时间轮，但是一直没有了解过它的实现原理。
最近有个和支付宝对接的项目，支付宝接口有流量控制，一定的时间内只允许 N 次接口调用，针对一些业务我们需要频繁调用支付宝开放平台接口，如果不对请求做限制，很容易触发流控告警。
为了避免这个问题，我们按照一定延迟规则将任务加载进时间轮内，通过时间轮的调度来实现接口异步调用。
很多开源框架都实现了时间轮算法，这里以 Netty 为例，看下 Netty 中时间轮是怎么实现的。
1.1 快速入门
下面是一个 API 使用例]]></description><category></category></item><item><title><![CDATA[性能远超AtomicLong，LongAdder原理完全解读]]></title><link>https://blog.youkuaiyun.com/codejas/article/details/111040120</link><guid>https://blog.youkuaiyun.com/codejas/article/details/111040120</guid><author>codejas</author><pubDate>Fri, 11 Dec 2020 16:21:04 +0800</pubDate><description><![CDATA[高并发场景下可以选择 AtomicLong 原子类进行计数等操作，除了 AtomicLong，在 jdk1.8 中还提供了 LongAdder。PS：AtomicLong 在 jdk1.5 版本提供。
AtomicLong 底层使用 Unsafe 的 CAS 实现，当操作失败时，会以自旋的方式重试，直至操作成功。因此在高并发场景下，可能会有很多线程处于重试状态，徒增 CPU 的压力，造成不必要的开销。
LongAdder 提供了一个 base 值，当竞争小的情况下 CAS 更新该值，如果 CAS 操作失败，]]></description><category></category></item><item><title><![CDATA[深入理解 Java 泛型擦除机制]]></title><link>https://blog.youkuaiyun.com/codejas/article/details/108282940</link><guid>https://blog.youkuaiyun.com/codejas/article/details/108282940</guid><author>codejas</author><pubDate>Fri, 28 Aug 2020 17:01:02 +0800</pubDate><description><![CDATA[我们都知道 Java 中的泛型可以在编译期对类型检查，避免类型强制转化带来的问题，保证代码的健壮性。不同语言对泛型的支持也不一样，Java 中的泛型类型在编译期会擦除，下面一个例子可以证明这一点：
	public static void main(String[] args) throws Exception {
        List&lt;String&gt; list = new ArrayList&lt;&gt;();
        list.add("abc");
        Class&]]></description><category></category></item><item><title><![CDATA[最通俗易懂的短链接原理讲解]]></title><link>https://blog.youkuaiyun.com/codejas/article/details/106102452</link><guid>https://blog.youkuaiyun.com/codejas/article/details/106102452</guid><author>codejas</author><pubDate>Wed, 13 May 2020 17:17:25 +0800</pubDate><description><![CDATA[看业务代码的时候，有些逻辑用到了短链接服务，感觉还蛮有意思的，这里简单的记录一下。

这种营销短信大家应该都收到过，短信有最大字符限制，而且为了更好的观感体验，短信里的链接一般都很短。现成的短链接生成服务也比较多，比如新浪、百度等，谷歌之前也有短链接服务，号称是最快的，但是在 2018 年关闭了。
一、短链接原理

我们点击短链接会发起一个 GET 方式的 HTTP 请求，当请求到对应的 API 后，会解析短链接里的标识获取到对应的长链接，然后重定向到长链接，这样整个流程就结束了。
比如我用新浪的短链接服务]]></description><category></category></item><item><title><![CDATA[Spring AOP 源码系列（一）解析 AOP 配置信息]]></title><link>https://blog.youkuaiyun.com/codejas/article/details/105542330</link><guid>https://blog.youkuaiyun.com/codejas/article/details/105542330</guid><author>codejas</author><pubDate>Wed, 15 Apr 2020 19:07:56 +0800</pubDate><description><![CDATA[在进行源码阅读之前建议先看一下这篇文章：Spring AOP 源码分析系列文章导读 by 田小波，写的非常好，推荐阅读。
关于 AOP 中常用的一些术语这里就不解释了，如果不清楚的建议先看一遍上面推荐的文章。
一、AOP 配置入口
在分析源码之前，我们先来看一下 XML 中关于 AOP 的配置：
    &lt;bean id="userServiceImpl" class="com.jas.me...]]></description><category></category></item><item><title><![CDATA[Spring IoC 源码导读]]></title><link>https://blog.youkuaiyun.com/codejas/article/details/105148594</link><guid>https://blog.youkuaiyun.com/codejas/article/details/105148594</guid><author>codejas</author><pubDate>Fri, 27 Mar 2020 19:30:48 +0800</pubDate><description><![CDATA[源码记录：spring-framework-5.1.7-source-code-read
文章导读

Spring IoC 源码系列（一）BeanDefinition 初始化与注册
Spring IoC 源码系列（二）IoC 容器启动流程分析
Spring IoC 源码系列（三）Spring 事件发布机制原理分析
Spring IoC 源码系列（四）bean创建流程与循环依赖问题分析
Spring...]]></description><category></category></item><item><title><![CDATA[Spring IoC 源码系列（五）getBean 流程分析]]></title><link>https://blog.youkuaiyun.com/codejas/article/details/105103636</link><guid>https://blog.youkuaiyun.com/codejas/article/details/105103636</guid><author>codejas</author><pubDate>Wed, 25 Mar 2020 20:29:10 +0800</pubDate><description><![CDATA[一、FactoryBean 用法讲解
在分析源码流程之前，我们先来看一下 FactoryBean，乍一看这家伙和 BeanFactory 很像，它们都可以用来获取 bean 对象，简单来说 FactoryBean 是一种可以生产 bean 的 bean，而 FactoryBean 是一个生产 bean 的工厂。
下面举个例子来简单说明一下 BeanFactory 的用法：
    // 定义一个 ...]]></description><category></category></item><item><title><![CDATA[Spring IoC 源码系列（四）bean创建流程与循环依赖问题分析]]></title><link>https://blog.youkuaiyun.com/codejas/article/details/104976152</link><guid>https://blog.youkuaiyun.com/codejas/article/details/104976152</guid><author>codejas</author><pubDate>Thu, 19 Mar 2020 20:46:59 +0800</pubDate><description><![CDATA[创建单例 bean 的代码细节在 org.springframework.beans.factory.support.AbstractBeanFactory#getBean 中，getBean 顾名思义是获取 bean 的流程，如果 bean 不存在的话会先创建，创建前与创建后的具体流程在下一篇文章里进行总结。这里只对创建 bean 的流程进行详细的分析。
1.入口
在 AbstractBeanF...]]></description><category></category></item><item><title><![CDATA[Web service 介绍与简单应用]]></title><link>https://blog.youkuaiyun.com/codejas/article/details/79593468</link><guid>https://blog.youkuaiyun.com/codejas/article/details/79593468</guid><author>codejas</author><pubDate>Mon, 16 Mar 2020 19:28:04 +0800</pubDate><description><![CDATA[一、Web service 介绍

1.1什么是Web service

到目前为止对Web service 没有统一的定义，这里以一种更容易理解的方式解释。Web service 是一个平台独立的，低耦合的，自包含的、基于可编程的web 的应用程序，即是一种跨编程语言和操作系统平台的远程调用技术。

Web service 技术， 能使得运行在不同机器上的不同应用无须借助附加的、专门的第三方软件...]]></description><category></category></item><item><title><![CDATA[Spring IoC 源码系列（三）Spring 事件发布机制原理分析]]></title><link>https://blog.youkuaiyun.com/codejas/article/details/104866357</link><guid>https://blog.youkuaiyun.com/codejas/article/details/104866357</guid><author>codejas</author><pubDate>Sat, 14 Mar 2020 19:41:00 +0800</pubDate><description><![CDATA[在 IoC 容器启动流程中有一个 finishRefresh 方法，具体实现如下：
	protected void finishRefresh() {
		clearResourceCaches();
		initLifecycleProcessor();
		getLifecycleProcessor().onRefresh();
		// 向所有监听 ContextRefreshedEvent...]]></description><category></category></item><item><title><![CDATA[业务总结003:抽奖活动]]></title><link>https://blog.youkuaiyun.com/codejas/article/details/104861112</link><guid>https://blog.youkuaiyun.com/codejas/article/details/104861112</guid><author>codejas</author><pubDate>Sat, 14 Mar 2020 15:27:25 +0800</pubDate><description><![CDATA[一、抽奖活动模型

上图是大概的抽奖活动模型，可能一个抽奖活动会持续很多天，这里活动抽奖规则、奖励库存都采用的都是当日的概念，当然也可以采用活动持续时长的概念，具体看产品的意愿，毕竟产品大大说了算。
二、抽奖算法
2.1 随机概率
在奖励池随机一个作为用户奖励，这种方式实现起来很简单，但是产品不允许。为了吸引用户参与抽奖，一般会设置一些成本较高的奖励，这些成本较高的奖励肯定不希望被用户大概率抽到。...]]></description><category></category></item><item><title><![CDATA[Spring IoC 源码系列（二）IoC 容器启动流程分析]]></title><link>https://blog.youkuaiyun.com/codejas/article/details/104848893</link><guid>https://blog.youkuaiyun.com/codejas/article/details/104848893</guid><author>codejas</author><pubDate>Fri, 13 Mar 2020 20:39:50 +0800</pubDate><description><![CDATA[private static final String configLocation = "applicationContext.xml";

    @Test
    public void beanTest() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(c...]]></description><category></category></item><item><title><![CDATA[Spring IoC 源码系列（一）BeanDefinition 初始化与注册]]></title><link>https://blog.youkuaiyun.com/codejas/article/details/104043474</link><guid>https://blog.youkuaiyun.com/codejas/article/details/104043474</guid><author>codejas</author><pubDate>Sun, 19 Jan 2020 17:37:19 +0800</pubDate><description><![CDATA[一、BeanDefinition
1.1 什么是 BeanDefinition
在一般的 Spring 项目中，主要通过 XML 的方式配置 bean，而 BeanDefinition 就是 XML 配置属性的载体，XML 文件首先会被转化成 Document 对象，通过解析 Document，把 XML 中 &lt;bean /&gt; 标签转化成 BeanDefinition 供 IoC 容器...]]></description><category></category></item><item><title><![CDATA[业务总结002:秒杀活动架构设计]]></title><link>https://blog.youkuaiyun.com/codejas/article/details/103735903</link><guid>https://blog.youkuaiyun.com/codejas/article/details/103735903</guid><author>codejas</author><pubDate>Fri, 27 Dec 2019 17:25:43 +0800</pubDate><description><![CDATA[一、秒杀商品模型

二、架构设计
2.1 Redis + MQ


缓存预热：秒杀商品一般时效性比较强，一场秒杀活动持续的时间不会很长，当在后台设置秒杀活动添加秒杀商品时，把商品对应的库存直接存到 Redis，但是要注意的是，设置缓存时一定要设置过期时间。
削减请求流量：当用户进到秒杀商品详情及后续所有操作都应当进行库存、秒杀资格校验
扣减 Redis 库存：当用户从秒杀商品详情到账单页请求下单时...]]></description><category></category></item><item><title><![CDATA[业务总结001:优惠券与礼包活动]]></title><link>https://blog.youkuaiyun.com/codejas/article/details/103685308</link><guid>https://blog.youkuaiyun.com/codejas/article/details/103685308</guid><author>codejas</author><pubDate>Tue, 24 Dec 2019 16:31:38 +0800</pubDate><description><![CDATA[优惠券相信大家在各大电商网站购物的时候都用过，有的时候领了一张券会想法设法的挑选商品来达到优惠券的使用金额，哪怕买了预期之外的商品也要把这张券用掉，褥羊毛的心态大部分人都有。
从产品的角度思考类似优惠券这种营销活动正是抓住了用户褥羊毛的心态，促进用户消费来增加商品的销量，从而赚取更多的利益。现在很多类电商产品在你注册之后会时不时的给你发一张券，当你有需求时还是很乐意去 app 上面买东西的。
最近...]]></description><category></category></item><item><title><![CDATA[lombok @Builder 是如何实现的]]></title><link>https://blog.youkuaiyun.com/codejas/article/details/100831594</link><guid>https://blog.youkuaiyun.com/codejas/article/details/100831594</guid><author>codejas</author><pubDate>Sat, 14 Sep 2019 17:36:59 +0800</pubDate><description><![CDATA[lombok 可能大家都用过，有一个 @Builder 注解可以很方便的在对象初始化的时候填充属性值，不用大量的调用 setter 方法，代码更易于阅读与编写。不知道大家有没有想过 @Builder 注解内部是怎么实现的，前些天看 《Effective Java》 的时候刚好看到有一个例子，其实很简单，这里以一个例子分享下代码实现。
定义 Builder 接口，用于 build 对象：
publi...]]></description><category></category></item><item><title><![CDATA[Java8 EnumSet 源码简单分析]]></title><link>https://blog.youkuaiyun.com/codejas/article/details/94636120</link><guid>https://blog.youkuaiyun.com/codejas/article/details/94636120</guid><author>codejas</author><pubDate>Thu, 04 Jul 2019 17:35:07 +0800</pubDate><description><![CDATA[一、EnumSet 概述
EnumSet 是一个用于存储枚举类型的 set 集合，一般的 set 集合底层都是使用对应的 map 实现的，但 EnumSet 是个特例，它底层使用一个 long 类型的整数或者数组实现。
下面我们先来看下它的使用方式：
public class EnumSetTest {
 
    public static void main(String[] args) {
...]]></description><category></category></item></channel></rss>