# alibaba阿里

返回开源:java | 返回开源首页

🐉 开源Java诊断工具Arthas antd

# 阿里 Mock 工具正式开源——TestableMock

back | github | 文档

功能十分强大,媲美 PowerMock,用法比 Mockito 还要简洁,还不挑框架,指哪换哪,一个 @MockMethod 注解打天下

它所承载的职责是 “让Java没有难测的方法”

# 主流Mock工具对比

在 TestableMock 开源之前,目前市面上主流的 Mock 工具主要有:

  • Mockito
  • Spock
  • PowerMock
  • JMockit
  • EasyMock

# 上手 TestableMock

  • pom配置
<properties>
    <testable.version>0.4.9</testable.version>
    <junit.version>5.6.2</junit.version>
</properties>

<dependencies>
    <dependency>
        <groupId>com.alibaba.testable</groupId>
        <artifactId>testable-all</artifactId>
        <version>${testable.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>${junit.version}</version>
        <scope>test</scope>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <configuration>
                <argLine>-javaagent:${settings.localRepository}/com/alibaba/testable/testable-agent/${testable.version}/testable-agent-${testable.version}.jar</argLine>
            </configuration>
        </plugin>
    </plugins>
</build>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  • 增加一个类,调用任意方法、成员方法、静态方法
/**
 * @from 来源:Java技术栈
 * @author 栈长
 */
public class TestableMock {

    /**
     * 调用任意方法
     */
    public String commonMethod() {
        return " www ".trim() + "." + " javastack".substring(1) + "www.javastack.cn".startsWith(".com");
    }

    /**
     * 调用成员、静态方法
     */
    public String memberMethod(String s) {
        return "{ \"result\": \"" + innerMethod(s) + staticMethod() + "\"}";
    }

    private static String staticMethod() {
        return "WWW_JAVASTACK_CN";
    }

    private String innerMethod(String website) {
        return "our website is: " + website;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
  • 增加测试类
import com.alibaba.testable.core.annotation.MockMethod;
import org.junit.jupiter.api.Test;

import static com.alibaba.testable.core.matcher.InvokeVerifier.verify;
import static org.junit.jupiter.api.Assertions.assertEquals;

/**
 * @author 栈长
 * @from 来源:Java技术栈
 */
class TestableMockTest {

    private TestableMock testableMock = new TestableMock();

    /**
     * Mock 任意方法
     * @return
     */
    @MockMethod(targetClass = String.class)
    private String trim() {
        return "http://www";
    }

    @MockMethod(targetClass = String.class, targetMethod = "substring")
    private String substr(int i) {
        return "javastack.cn_";
    }

    @MockMethod(targetClass = String.class)
    private boolean startsWith(String website) {
        return false;
    }

    /**
     * Mock 成员方法
     * @param text
     * @return
     */
    @MockMethod(targetClass = TestableMock.class)
    private String innerMethod(String text) {
        return "mock_" + text;
    }

    /**
     * Mock 静态方法
     * @return
     */
    @MockMethod(targetClass = TestableMock.class)
    private String staticMethod() {
        return "_MOCK_JAVASTACK";
    }

    @Test
    void commonMethodTest() {
        assertEquals("http://www.javastack.cn_false", testableMock.commonMethod());
        verify("trim").withTimes(1);
        verify("substr").withTimes(1);
        verify("startsWith").withTimes(1);
    }

    @Test
    void memberMethodTest() {
        assertEquals("{ \"result\": \"mock_hello_MOCK_JAVASTACK\"}", testableMock.memberMethod("hello"));
        verify("innerMethod").withTimes(1);
        verify("staticMethod").withTimes(1);
        verify("innerMethod").with("hello");
        verify("staticMethod").with();
    }
   
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

# 阿里巴巴开源的超轻量的跨平台图形渲染引擎——GCanvas

back

GCanvas是由阿里巴巴开发的用于移动设备的跨平台渲染引擎。它是使用基于OpenGL ES的C ++编写的,因此可以为Javascript运行时提供高性能的2D / WebGL渲染功能。它还具有类似于浏览器的canvas API,因此使用非常方便且灵活,特别是对于Web开发人员而言。支持的操作系统有Android 4.0+(API 14)和iOS 8.0+。

# 示例

import { enable, WeexBridge, Image as GImage } from "@gcanvas/core";

var gcanvas = enable(this.$refs.canvas_holder, {bridge: WeexBridge});
var ctx = gcanvas.getContext("2d");
//rect
ctx.fillStyle = 'red';
ctx.fillRect(0, 0, 100, 100);

//rect
ctx.fillStyle = 'black';
ctx.fillRect(100, 100, 100, 100);
ctx.fillRect(25, 210, 700, 5);

//circle
ctx.arc(450, 200, 100, 0, Math.PI * 2, true);
ctx.fill();

var image = new GImage();
image.src = 'TB1KwRTlh6I8KJjy0FgXXXXzVXa-225-75.png';
image.onload = function(){
 ctx.drawImage(image, 100, 300);
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# Egg 2.24.0 发布,企业级 Node.js 框架

Egg 2.24.0 发布了,Egg 是阿里开源的企业级 Node.js 框架,为企业级框架和应用而生。团队的架构师和技术负责人可以非常容易地基于自身的技术架构在其基础上扩展出适合自身业务场景的框架。

# RocketMQ

back | 返回:专题-消息中间件

由阿里自研的RocketMQ更是经历了多年的双十一高并发挑战,其中4.3.0版本推出了事务消息的新特性本文对RocketMQ 4.5.0版本事务消息相关的源码跟踪介绍,通过阅读可以知道:

  • 事务消息解决什么样的问题
  • 事务消息的实现原理及其设计亮点

# 解决什么问题

假设我所在的系统现在有这样一个场景:

本地开启数据库事务进行扣款操作,成功后发送MQ消息给库存中心进行发货。
有人会想到开启mybatis事务实现,把本地事务和MQ消息放在一起不就行了吗?如果MQ发送成功,就提交事务,发送失败就回滚事务,整套操作一气呵成。

既然MQ消息的发送不能和本地事务写在一起,那如何来保证其整体具有原子性的需求呢?答案就是今天我们介绍的主角:事务消息

# 概览

总体而言RocketMQ事务消息分为两条主线

  • 定时任务发送流程:发送half message(半消息),执行本地事务,发送事务执行结果
  • 定时任务回查流程:MQ服务器回查本地事务,发送事务执行结果

# 源码分析

# 半消息发送流程

本地应用(client)

在本地应用发送事务消息的核心类是TransactionMQProducer,该类通过继承DefaultMQProducer来复用大部分发送消息相关的逻辑,这个类的代码量非常少只有100来行,下面是这个类的sendMessageTransaction方法

# jetcache

back | 返回:专题-缓存 | github

Jetcache是阿里开源的一个缓存抽象工具集。它提供了TTL二级缓存分布式缓存更新等强大的注解功能,
也支持代码逻辑手动调用api。比spring原生cache注解功能更丰富,更简单易用。
当前有四个实现,RedisCacheTairCache(此部分未在github开源)CaffeineCache(in memory)和一个简易的LinkedHashMapCache(in memory),要添加新的实现也是非常简单的。

# 依赖

  • springboot
<!-- https://mvnrepository.com/artifact/com.alicp.jetcache/jetcache-starter-redis -->
<dependency>
    <groupId>com.alicp.jetcache</groupId>
    <artifactId>jetcache-starter-redis</artifactId>
    <version>2.6.0.M3</version>
</dependency>
1
2
3
4
5
6
  • 如果没有springboot
<!-- 如果没有使用spring boot,可以按下面的方式配置(这里使用jedis客户端连接redis为例)。 -->
<dependency>
    <groupId>com.alicp.jetcache</groupId>
    <artifactId>jetcache-anno</artifactId>
    <version>2.4.4</version>
</dependency>
<dependency>
    <groupId>com.alicp.jetcache</groupId>
    <artifactId>jetcache-redis</artifactId>
    <version>2.4.4</version>
</dependency>
1
2
3
4
5
6
7
8
9
10
11

配置了这个JetCacheConfig类以后,可以使用@CreateCache@Cached注解。

import java.util.HashMap;
import java.util.Map;

import com.alicp.jetcache.anno.CacheConsts;
import com.alicp.jetcache.anno.config.EnableCreateCacheAnnotation;
import com.alicp.jetcache.anno.config.EnableMethodCache;
import com.alicp.jetcache.anno.support.GlobalCacheConfig;
import com.alicp.jetcache.anno.support.SpringConfigProvider;
import com.alicp.jetcache.embedded.EmbeddedCacheBuilder;
import com.alicp.jetcache.embedded.LinkedHashMapCacheBuilder;
import com.alicp.jetcache.redis.RedisCacheBuilder;
import com.alicp.jetcache.support.FastjsonKeyConvertor;
import com.alicp.jetcache.support.JavaValueDecoder;
import com.alicp.jetcache.support.JavaValueEncoder;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.util.Pool;

@Configuration
@EnableMethodCache(basePackages = "com.company.mypackage")
@EnableCreateCacheAnnotation
public class JetCacheConfig {

    @Bean
    public Pool<Jedis> pool(){
        GenericObjectPoolConfig pc = new GenericObjectPoolConfig();
        pc.setMinIdle(2);
        pc.setMaxIdle(10);
        pc.setMaxTotal(10);
        return new JedisPool(pc, "localhost", 6379);
    }

    @Bean
    public SpringConfigProvider springConfigProvider() {
        return new SpringConfigProvider();
    }

    @Bean
    public GlobalCacheConfig config(SpringConfigProvider configProvider, Pool<Jedis> pool){
        Map localBuilders = new HashMap();
        EmbeddedCacheBuilder localBuilder = LinkedHashMapCacheBuilder
                .createLinkedHashMapCacheBuilder()
                .keyConvertor(FastjsonKeyConvertor.INSTANCE);
        localBuilders.put(CacheConsts.DEFAULT_AREA, localBuilder);

        Map remoteBuilders = new HashMap();
        RedisCacheBuilder remoteCacheBuilder = RedisCacheBuilder.createRedisCacheBuilder()
                .keyConvertor(FastjsonKeyConvertor.INSTANCE)
                .valueEncoder(JavaValueEncoder.INSTANCE)
                .valueDecoder(JavaValueDecoder.INSTANCE)
                .jedisPool(pool);
        remoteBuilders.put(CacheConsts.DEFAULT_AREA, remoteCacheBuilder);

        GlobalCacheConfig globalCacheConfig = new GlobalCacheConfig();
        globalCacheConfig.setConfigProvider(configProvider);
        globalCacheConfig.setLocalCacheBuilders(localBuilders);
        globalCacheConfig.setRemoteCacheBuilders(remoteBuilders);
        globalCacheConfig.setStatIntervalMinutes(15);
        globalCacheConfig.setAreaInCacheName(false);

        return globalCacheConfig;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

# 添加配置

jetcache:
  statIntervalMinutes: 15
  areaInCacheName: false
  local:
    default:
      type: linkedhashmap
      keyConvertor: fastjson
  remote:
    default:
      type: redis
      keyConvertor: fastjson
      valueEncoder: java
      valueDecoder: java
      keyPrefix: "test:prefix:"#定义redis的key前缀
      poolConfig:
        minIdle: 5
        maxIdle: 20
        maxTotal: 50
      host: 127.0.0.1
      port: 6379
      password: #定义redis访问密码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 打开开关

EnableMethodCacheEnableCreateCacheAnnotation这两个注解分别激活Cached和CreateCache注解

import com.alicp.jetcache.anno.config.EnableCreateCacheAnnotation;
import com.alicp.jetcache.anno.config.EnableMethodCache;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableMethodCache(basePackages = "com.company.mypackage")
@EnableCreateCacheAnnotation
public class MySpringBootApp {
    public static void main(String[] args) {
        SpringApplication.run(MySpringBootApp.class);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# fastjson

back:泛型 | 返回:JSON |GitBub_fastjson

主要特点:快速FAST (比其它任何基于Java的解析器和生成器更快,包括jackson);强大(支持普通JDK类包括任意Java Bean Class、Collection、Map、Date或enum);零依赖(没有依赖其它任何类库除了JDK)。

看到下面这段代码,简单的意思就是从redis 获取字符串,然后转换为指定的泛型的类。大家可以留意到这里创建了个TypeReference 匿名类 注意后面是有带{}的,所以是实例化一个匿名内部类(这是重点中的重点,一切的魔术从这里开始),而不是TypeReference 这个类的实例

List<ResourceEntity> resources =
    redisAdapter.get(BaseConstant.TENANT_CODE_SYSTEM, CacheKey.KEY_ALL_RESOURCE,
        new TypeReference<List<ResourceEntity>>() {
        });
1
2
3
4

# 阿里巴巴阿里云UI组件库已开源——console-components

back | github

console-components 是针对阿里云控制台场景的 React 组件库,基于Alibaba Fusion组件库实现。该项目的代号为Wind。

# 分布式应用服务开发的一站式解决方案_Spring_Cloud_Alibaba

back

GitHub

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2.1.0.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
1
2
3
4
5
6
7
8
9
10
11

# Ant_Design

back

back——GitHub_Ant-Design——GitHub_Ant-Design-Pro——ant-design

# JDBC连接池、监控组件_Druid

back——GitHub_Druid

  1. 监控数据库访问性能。
  2. 提供了一个高效、功能强大、可扩展性好的数据库连接池。
  3. 数据库密码加密。
  4. SQL执行日志。

# Java的JSON处理器fastjson

back

back——GitBub_fastjson

主要特点:快速FAST (比其它任何基于Java的解析器和生成器更快,包括jackson);强大(支持普通JDK类包括任意Java Bean Class、Collection、Map、Date或enum);零依赖(没有依赖其它任何类库除了JDK)。

# 服务框架Dubbo

back——GitHub_Dubbo

Apache Dubbo (incubating) |是阿里巴巴的一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。

# 企业级流式计算引擎JStorm

back——GitHub_JStorm

JStorm 是参考 Apache Storm 实现的实时流式计算框架,在网络IO、线程模型、资源调度、可用性及稳定性上做了持续改进,已被越来越多企业使用。JStorm 可以看作是 storm 的 java 增强版本,除了内核用纯java实现外,还包括了thrift、python、facet ui。从架构上看,其本质是一个基于 zk 的分布式调度系统。

# apns4j

back——GitHub_apns4j

apns4j 是 Apple Push Notification Service 的 Java 实现。

# 数据驱动的高交互可视化图形语法AntV-G2

back——GitHub_G2

G2 是一套基于可视化编码的图形语法,以数据驱动,具有高度的易用性和扩展性,用户无需关注各种繁琐的实现细节,一条语句即可构建出各种各样的可交互的统计图表。
同时,G2 也是 AntV 最重要的组成,始于《The Grammar of Graphics》一书描述的视觉编码语法系统(这也是 G2 项目命名的由来)。

# 前端构建和工程化工具Dawn

back——GitHub_Dawn

它通过 pipeline 和 middleware 将开发过程抽象为相对固定的阶段和有限的操作,简化并统一了开发人员的日常构建与开发相关的工作。

# 分布式数据层TDDL

back——GitHub_tddl

TDDL 是一个基于集中式配置的 jdbc datasource实现,具有主备,读写分离,动态数据库配置等功能。

# 轻量级分布式数据访问层CobarClient

back——GitHub_CC

# 淘宝定制JVM_TaobaoJVM

back——官網

TaobaoJVM 基于 OpenJDK HotSpot VM,是国内第一个优化、定制且开源的服务器版Java虚拟机。目前已经在淘宝、天猫上线,全部替换了Oracle官方JVM版本,在性能,功能上都初步体现了它的价值。

# Java图片处理类库SimpleImage

back——GitHub_simpleImage

SimpleImage是阿里巴巴的一个Java图片处理的类库,可以实现图片缩略、水印等处理。

# Redis的Java客户端Tedis

GitHub

# 动态服务发现、配置和服务管理平台Nacos

back

Nacos使用

# 高可用流量管理框架Sentinel

github——参照其中sentinel章节

# Java解析Excel工具easyexcel

back——github——参考导出专题中easyExcel

# 基于SpringBoot的研发框架SOFABoot

github

SOFABoot 是蚂蚁金服开源的基于 Spring Boot 的研发框架,它在 Spring Boot 的基础上,提供了诸如 Readiness Check,类隔离,日志空间隔离等等能力。在增强了 Spring Boot 的同时,SOFABoot 提供了让用户可以在 Spring Boot 中非常方便地使用 SOFAStack 相关中间件的能力。

# 动态非侵入AOP解决方案JVM-Sandbox

github

JVM-Sandbox,JVM 沙箱容器,一种基于 JVM 的非侵入式运行期 AOP 解决方案。

# 面向云的分布式消息领域标准OpenMessaging

back——github

OpenMessaging 是由阿里巴巴发起,与雅虎、滴滴出行、Streamlio 公司共同参与创立,旨在创立厂商无关、平台无关的分布式消息及流处理领域的应用开发标准。

# P2P文件分发系统Dragonfly

github

Dragonfly(蜻蜓)是阿里自研的 P2P 文件分发系统,用于解决大规模文件分发场景下分发耗时、成功率低、带宽浪费等难题。大幅提升发布部署、数据预热、大规模容器镜像分发等业务能力。

# LayoutManager定制化布局方案vlayout

back——github

VirtualLayout是一个针对RecyclerView的LayoutManager扩展, 主要提供一整套布局方案和布局间的组件复用的问题。

# canal

back——github——wiki

TIP

MySQL 数据库 binlog 的增量订阅、消费组件。模拟 MySQL salve 方式,实现 MySQL 的主从同步,同时加入了增量日志解析等功能。