【发布时间】:2021-07-09 04:09:18
【问题描述】:
我目前正在开展一个管理预订系统的项目。
有一个新要求,即能够跟踪所有预订状态的变化。
我希望这不会影响现有的逻辑,并作为一个独立的模块存在。
一开始我想到了AOP,但是有一些问题。
这个请求应该记录什么数据是如何被什么操作改变的。
我认为我可以通过将 AOP 应用于存储库的保存方法来提取不同的数据。
但是,这是不可能的,因为有许多不同的操作会更新数据。
例如,对于预订,使用存储库中的保存方法进行更新,但此方法用于签入、签出等各种操作。
因此,可以得到数据的差异,但无法判断数据是由哪个动作更新的。
@Service
public class BookingService {
@Autowired
private BookingRepository bookingRepository;
public Booking create(Booking booking) {
return bookingRepository.save(booking);
}
public void update(Booking booking) {
Booking oldBooking = bookingRepository.findById(booking.getId()).orElseThrow(() -> new RuntimeException("Entity not found"));
oldBooking.update(booking);
bookingRepository.save(oldBooking);
}
public void checkIn(long id) {
Booking booking = bookingRepository.findById(id).orElseThrow(() -> new RuntimeException("Entity not found"));
booking.setStatus(Booking.Status.CheckIn);
bookingRepository.save(booking);
}
}
而且由于我使用AOP,我不希望现有逻辑的参数或结果值适合某种形式。
在考虑如何解决这个问题时,如何使用 Mockito 使用的方法。
在 Mockito 中,我们可以知道一个方法何时在一个方法内执行。
难道不能创建这样的方法吗?
@Aspect
public class BookingHistory {
@Autowired
private BookingRepository bookingRepository;
@Around("execution(* *Service.update(..))")
public void update(ProceedingJoinPoint proceedingJoinPoint) {
long id = getBookingId(proceedingJoinPoint);
Booking origin = getBooking(id);
final DiffData diffData;
when(bookingRepository::save).thenReturn(result -> diffData = diff(origin, result));
saveHistory("UPDATE", "Booking", diffData);
}
}
但我不知道如何在 Mockito 中实现“when”、“thenReturn”等。
我能否获得一些实现 Mockito 的提示?
如果不是这样,有没有其他好的方法?
【问题讨论】:
-
您使用什么持久性? JPA?普通的 JDBC?或者...
-
Spring 数据 JPA。
-
假设你正在使用 Hibernate,只需使用 Hibernate Envers。哪个是开箱即用的,或者如果你想要别的东西,你也可以使用 JaVers。你不需要自己动手。如果所有其他方法都失败了,您甚至可以使用数据库上的触发器来执行此操作,以将原始数据复制到审计表中。如果你愿意,不需要在 java 中做。
-
这根本不是 AOP 的工作方式。如果您想影响
save的返回值,只需编写一个带有截取其执行的切入点的建议,在那里执行您的差异操作并保存到审核日志中。如果您要发布完整的MCVE,我可以在本地运行它并提出具体建议。您目前正在隐藏信息,例如getBookingId(proceedingJoinPoint)做了什么,Booking类看起来像什么等等。但据我所知,如果你不喜欢 Javers,你可以使用 AOP 轻松解决问题。
标签: java spring architecture aop aspect