项目中经常会写一种数据组装逻辑:根据 ID 或 Name 查询引用数据,并组装到原数据行。比如,这里有一个书籍列表。
1 2 3 4 5 6 7 8 9 10
| [ { "name": "红楼梦", "authorId": 12 }, { "name": "Why Github?", "authorId": 13 } ]
|
我们需要提取列表中的 authorId,并调用某个 RPC 接口或本地接口,查询到对应的用户列表,然后逐一合并,形成最终的数据结构,如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| [ { "name": "红楼梦", "author": { "id": 12, "name": "曹雪芹" } }, { "name": "Why Github?", "author": { "id": 13, "name": "cooocy" } } ]
|
这种代码既没什么技术含量,又大量重复,并且写多了会污染我们的核心代码。这里提供一个基于 Spring AOP
实现的通用处理框架。
使用
在基础对象类 Book
和 BookRepository
中的查询方法中增加如下注解。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class Book { String name; @Ref(analyzer = UserRepository.class, refField = "id", analysisTo = "author") Long authorId; @Transient UserShadow author; }
class BookRepository { @RefAnalysis List<Book> findAll(); }
|
新增或修改原有的用户查询接口,使之实现 RefAnalyzer
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| class UserRepository implements RefAnalyzer<UserShadow, User, Long> {
Publisher findOne(Long id) { }
List<Publisher> findMany(List<Long> ids) { } User fallback(Long id) { return new User(id, "Unknown"); } UserShadow convert(User user) { return new UserShadow(); }
}
|
另外考虑的一些深层引用,还可以使用 @DeepRef
进行深层引用,可以参考 github 源码,在最下方提供了链接。
源代码
Rennala