JoinInMemory 注解属性和AbstractJoinItemExecutor基本一致,在此就不做赘述,我们先看下具体的使用方式:
@Datapublic class OrderDetailVOAnnV1 extends OrderDetailVO {private final OrderVO order;@JoinInMemory(keyFromSourceData = https://www.isolves.com/it/cxkf/jiagou/2023-12-14/"#{order.userId}",keyFromJoinData = "#{id}",loader = "#{@userRepository.getByIds(#root)}",joinDataConverter = "#{T(com.geekhalo.lego.joininmemory.order.UserVO).apply(#root)}")private UserVO user;// 其他暂时忽略}@Datapublic class OrderListVOAnnV1 extends OrderListVO {private final OrderVO order;@JoinInMemory(keyFromSourceData = "#{order.userId}",keyFromJoinData = "#{id}",loader = "#{@userRepository.getByIds(#root)}",joinDataConverter = "#{T(com.geekhalo.lego.joininmemory.order.UserVO).apply(#root)}")private UserVO user;// 其他暂时忽略}我们以 UserVO user 属性为例

文章插图
@JoinInMemory 注解中大量使用 SpEL , 不熟悉的伙伴可以自行网上进行检索 。
其他部分不变,定义 OrderService 如下:
@Servicepublic class OrderServiceAnnV1 implements OrderService {@Autowiredprivate OrderRepository orderRepository;@Autowiredprivate JoinService joinService;@Overridepublic List<OrderListVO> getByUserId(Long userId) {List<Order> orders = this.orderRepository.getByUserId(userId);List<OrderListVOAnnV1> orderDetailVOS = orders.stream().map(order -> new OrderListVOAnnV1(OrderVO.apply(order))).collect(toList());this.joinService.joinInMemory(OrderListVOAnnV1.class, orderDetailVOS);return orderDetailVOS.stream().collect(toList());}@Overridepublic OrderDetailVO getDetailByOrderId(Long orderId) {Order order = this.orderRepository.getById(orderId);OrderDetailVOAnnV1 orderDetail = new OrderDetailVOAnnV1(OrderVO.apply(order));this.joinService.joinInMemory(OrderDetailVOAnnV1.class, Arrays.asList(orderDetail));return orderDetail;}}相对于 Fetcher 抽象,我们将 Fetcher、FetcherExecutor 全部配置化,并通过 注解的方式进行呈现,相对于 Coding 方案,注解方案更加灵活,工作量也更小 。5.2. 复杂配置 @Alias 来帮忙相对于 Fetcher 封装,一个 @JoinInMemory 成功干掉了两个组件,但观其自身配置起来还是非常繁琐 。比如,在订单查询这个场景,在 OrderListVO 和 OrderDetailVO 中都需要对 UserVO 进行数据绑定,观察两个注解 , 我们会发现很多重复配置:
//OrderListVO@JoinInMemory(keyFromSourceData = https://www.isolves.com/it/cxkf/jiagou/2023-12-14/"#{order.userId}",keyFromJoinData = "#{id}",loader = "#{@userRepository.getByIds(#root)}",joinDataConverter = "#{T(com.geekhalo.lego.joininmemory.order.UserVO).apply(#root)}")private UserVO user;// OrderDetailVO@JoinInMemory(keyFromSourceData = "#{order.userId}",keyFromJoinData = "#{id}",loader = "#{@userRepository.getByIds(#root)}",joinDataConverter = "#{T(com.geekhalo.lego.joininmemory.order.UserVO).apply(#root)}")private UserVO user;两个配置完全一样,细品之后会发现:【变化】入参变化,读取的属性不同,只是本次恰巧相同而已
- OrderListVO 指的是 OrderListVO 属性 order 的id值
- OrderDetailVO 指的是 OrderDetailVO 属性 order 的值
- keyFromJoinData 指的是 user对象的 id
- loader 指的是通过 userRepository 的 getByIds 加载数据
- joinDataConverter 指的是将 user 转换为 UserVO
- 将绑定结果 UserVO 绑定到属性上(属性名不同没有影响)
自定义注解 结合 Spring @AliasFor 便可以解决这个问题,以 UserVO 为例:
@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)// 管理通用属性@JoinInMemory(keyFromSourceData = https://www.isolves.com/it/cxkf/jiagou/2023-12-14/"",keyFromJoinData = "#{id}",loader = "#{@userRepository.getByIds(#root)}",joinDataConverter = "#{T(com.geekhalo.lego.joininmemory.order.UserVO).apply(#root)}")public @interface JoinUserVOOnId {// 使用别名将 keyFromSourceData 的配置暴露出来@AliasFor(annotation = JoinInMemory.class)String keyFromSourceData();}新注解有如下几个特点:- 在注解上使用 @JoinInMemory 注解完成对通用属性的配置
- 在自定义注解 JoinUserVOOnId 的 keyFromSourceData 属性上,添加 @AliasFor 注解,将配置暴露给使用方
推荐阅读
- 能如何看电脑内存,如何查看电脑c盘和d盘内存
- 你知道怎样在 Python 中管理内存吗
- 如何查看手机运行内存大小,如何查看手机软件占用的内存
- 能咋滴看电脑内存,怎么查看自己电脑内存多大
- sd卡和内存卡有什么区别
- 电脑能插3根内存条,电脑能咋滴共存两个窗口
- 苹果手机怎么在电脑上清理内存,苹果手机怎样可以清理内存拉圾
- oppo reno ace能插内存卡吗
- 手机内存满了该怎么处理,手机里照片太多,占内存太多该怎么办?
- 能咋地看电脑内存,如何查看电脑的内存条型号大小
