spring-boot-data-aggregator-autoconfigure

Parent pom providing dependency and plugin management for applications built with Maven

License

License

Categories

Categories

Spring Boot Container Microservices Data Auto Application Layer Libs Code Generators config Configuration
GroupId

GroupId

io.github.lvyahui8
ArtifactId

ArtifactId

spring-boot-data-aggregator-autoconfigure
Last Version

Last Version

1.1.3
Release Date

Release Date

Type

Type

jar
Description

Description

spring-boot-data-aggregator-autoconfigure
Parent pom providing dependency and plugin management for applications built with Maven
Project URL

Project URL

https://projects.spring.io/spring-boot/#/spring-boot-starter-parent/spring-boot-data-aggregator-autoconfigure

Download spring-boot-data-aggregator-autoconfigure

How to add to project

<!-- https://jarcasting.com/artifacts/io.github.lvyahui8/spring-boot-data-aggregator-autoconfigure/ -->
<dependency>
    <groupId>io.github.lvyahui8</groupId>
    <artifactId>spring-boot-data-aggregator-autoconfigure</artifactId>
    <version>1.1.3</version>
</dependency>
// https://jarcasting.com/artifacts/io.github.lvyahui8/spring-boot-data-aggregator-autoconfigure/
implementation 'io.github.lvyahui8:spring-boot-data-aggregator-autoconfigure:1.1.3'
// https://jarcasting.com/artifacts/io.github.lvyahui8/spring-boot-data-aggregator-autoconfigure/
implementation ("io.github.lvyahui8:spring-boot-data-aggregator-autoconfigure:1.1.3")
'io.github.lvyahui8:spring-boot-data-aggregator-autoconfigure:jar:1.1.3'
<dependency org="io.github.lvyahui8" name="spring-boot-data-aggregator-autoconfigure" rev="1.1.3">
  <artifact name="spring-boot-data-aggregator-autoconfigure" type="jar" />
</dependency>
@Grapes(
@Grab(group='io.github.lvyahui8', module='spring-boot-data-aggregator-autoconfigure', version='1.1.3')
)
libraryDependencies += "io.github.lvyahui8" % "spring-boot-data-aggregator-autoconfigure" % "1.1.3"
[io.github.lvyahui8/spring-boot-data-aggregator-autoconfigure "1.1.3"]

Dependencies

compile (5)

Group / Artifact Type Version
org.springframework.boot : spring-boot-configuration-processor Optional jar 2.1.1.RELEASE
org.springframework.boot : spring-boot-autoconfigure jar 2.1.1.RELEASE
org.projectlombok : lombok jar 1.18.8
org.reflections : reflections jar 0.9.11
io.github.lvyahui8 : spring-boot-data-aggregator-core jar 1.1.3

Project Modules

There are no modules declared in this project.

Spring Boot 并行数据聚合库

Build Status Codecov License Maven Central GitHub release

Total alerts Language grade: Java

基于注解实现并行地依赖注入(调用),可以看做 Spring @Async 注解的升级版。

image-20200309230202047

特性

  • 异步获取依赖

    所有 @DataConsumer 定义的依赖将异步获取. 当provider方法参数中的所有依赖获取完成, 才执行provider方法

  • 不限级嵌套

    依赖关系支持深层嵌套. 下面的示例只有一层

  • 异常处理

    目前支持两种处理方式: 忽略or终止

    忽略是指provider方法在执行时, 忽略抛出的异常并return null值; 终止是指一旦有一个provider方法抛出了异常, 将逐级向上抛出, 终止后续处理.

    配置支持consumer级或者全局, 优先级 : consumer级 > 全局

  • 查询缓存

    在调用Facade的query方法的一次查询生命周期内, 方法调用结果可能复用, 只要方法签名以及传参一致, 则默认方法是幂等的, 将直接使用缓存的查询结果. 但这个不是绝对的, 考虑到多线程的特性, 可能有时候不会使用缓存

  • 超时控制

    @DataProvider 注解支持配置timeout, 超时将抛出中断异常 (InterruptedException), 遵循异常处理逻辑

使用方法

1. 配置

pom.xml

<dependency>
  <groupId>io.github.lvyahui8</groupId>
  <artifactId>spring-boot-data-aggregator-starter</artifactId>
  <version>{$LATEST_VERSION}</version>
</dependency>

application.properties

# 指定要扫描注解的包
io.github.lvyahui8.spring.base-packages=io.github.lvyahui8.spring.example

2. 添加注解

  • @DataProvider 定义数据提供者
  • @DataConsumer 定义方法参数依赖类型为其他接口返回值, 其他接口是一个@DataProvider
  • @InvokeParameter 定义方法参数依赖类型为用户输入值

3. 查询

通过 DataFacade.get 静态门面查询指定数据

示例

开发一个用户汇总数据接口, 包括用户的基础信息和博客列表

1. 定义提供基础数据的"原子"服务

使用@DataProvider定义接口为数据提供者

使用@InvokeParameter指定要传递的用户输入参数

博客列表服务

需要参数userId

@Service
public class PostServiceImpl implements PostService {
    @DataProvider("posts")
    @Override
    public List<Post> getPosts(@InvokeParameter("userId") Long userId) {

用户基础信息查询服务

需要参数userId

@Service
public class UserServiceImpl implements UserService {
    @DataProvider("user")
    @Override
    public User get(@InvokeParameter("userId") Long id) {

2. 调用聚合接口

方式一: 函数式调用

注意这里不能将函数式调用改为Lambda表达式, 两者的实际行为是不一致的.

User user = DataFacade.get(
     Collections.singletonMap("userId", 1L), 
     new Function2<User, List<Post>, User>() {
            @Override
            public User apply(@DataConsumer("user") User user, 
                              @DataConsumer("posts") List<Post> posts) {
                user.setPosts(posts);
                return user;
            }
     });
Assert.notNull(user,"User must not be NULL");
Assert.notNull(user.getPosts(),"User's posts must not be NULL");

方式二: 定义聚合层查询

组合@DataProvider \ @DataConsumer \ @InvokeParameter 实现汇聚功能

@Component
public class UserAggregate {
    @DataProvider("userWithPosts")
    public User userWithPosts(
            @DataConsumer("user") User user,
            @DataConsumer("posts") List<Post> posts) {
        user.setPosts(posts);
        return user;
    }
}

指定要查询的data id, 查询参数, 返回值类型, 并调用facade.get方法即可

User user = DataFacade.get(/*data id*/ "userWithPosts",
                            /*Invoke Parameters*/
                            Collections.singletonMap("userId",1L), 
                            User.class);
Assert.notNull(user,"User must not be NULL");
Assert.notNull(user.getPosts(),"User's posts must not be NULL");

运行结果

可以看到, user 和posts是由异步线程执行查询, 而userWithPosts是主调线程执行, 其中

  • 基础user信息查询耗费时间 1000ms
  • 用户博客列表查询耗费时间 1000ms
  • 总的查询时间 1005ms
[aggregateTask-1]  query id: user, costTime: 1000ms, resultType: User,  invokeMethod: UserServiceImpl#get
[aggregateTask-2]  query id: posts, costTime: 1000ms, resultType: List,  invokeMethod: PostServiceImpl#getPosts
[           main]  query id: userWithPosts, costTime: 1010ms, resultType: User,  invokeMethod: UserAggregate#userWithPosts
[           main]  user.name:lvyahui8,user.posts.size:1

贡献者

Versions

Version
1.1.3
1.1.2
1.1.1
1.1.0
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0-RELEASE