我想知道在自定义对象映射器内部调用/注入(微)服务是否是一种好习惯。
此映射器将实体转换为DTO。在此DTO中,存在一个包含一些值的总和的字段(需要一些业务逻辑)。我定义了一种服务,以集中使用在许多其他地方使用的逻辑。
答案 0 :(得分:2)
严格来说,从映射器调用服务并没有错,但是它确实向映射器添加了依赖关系,该映射器通常是一个纯对象(Plain Old Java Object,POJO),可以将一种类型的对象简单地转换为另一种类型。一种替代方法是将所需信息作为参数传递给映射器。例如,假设您当前的设计类似于以下内容:
public class Foo { /* ... */}
public class FooDto { /* ... */}
public class FooService {
public FooResults getSomeResults() { /* ... */ }
}
public class FooMapper {
private final FooService service;
public FooMapper(FooService service) {
this.service = service;
}
public FooDto convert(Foo foo) {
FooResults results = service.getSomeResults();
// ... use results ...
}
}
您可以将FooMapper
作为参数传递给FooService
方法,而不是使FooResults
依赖于convert
:
public class FooMapper {
public FooDto convert(Foo foo, FooResults results) {
// ... use results ...
}
}
此方法的优点是FooMapper
不再依赖于FooService
。相反,调用convert
方法的客户端必须具有对FooService
的引用才能获取FooResults
对象。
答案 1 :(得分:1)
映射器将一个数据结构转换为另一个数据结构。因此,它仅应依赖于这两个数据结构之一。
+------------------+ +----------+ +------------------+
| data structure 1 | <----- | mapper | -----> | data structure 2 |
+------------------+ +----------+ +------------------+
如果映射器使用服务,则它也依赖于该服务。这意味着它知道如何获取数据。我想您的映射器取决于具体的服务。因此,对于其中一种数据结构的更改以及对该服务的更改,映射器将受到影响。
+------------------+ +----------+ +------------------+
| data structure 1 | <----- | mapper | -----> | data structure 2 |
+------------------+ +----------+ +------------------+
|
V
+----------+
| service |
+----------+
模拟服务进行测试可能很困难。也许服务依赖某种存储库,或者它本身就是SQL。
通过引入一个从获取数据的方式中抽象出来的接口,使映射器独立于数据结构的源可能会更好。然后,您的服务可以实现该接口或创建一个简单的适配器。
+------------------+ +----------+ +------------------+
| data structure 1 | <----- | mapper | -----> | data structure 2 |
+------------------+ +----------+ +------------------+
|
V
+------------------+ +--------------+
| Data1Provider | <------ | service |
+------------------+ +--------------+
使用这种方法,可以通过引入如何获取数据的稳定抽象来逆转对服务的依赖性。这就是所谓的依赖反转。
它可能是一个看起来像这样的简单界面
public interface Data1Provider {
public FooResults getResults();
}
可以轻松模拟该界面以进行测试。
另一种好的方法是在调用映射器之前简单地调用服务。只需将服务返回的数据传递给映射器即可。我不会在这里详细介绍,因为Justin Albano's的答案已经显示出来了。