Spring 依赖服务应在何处@Autowired(控制器或服务)?

Spring 依赖服务应在何处@Autowired(控制器或服务)?,spring,service,architecture,autowired,Spring,Service,Architecture,Autowired,考虑以下两个选项: 选项#1:在控制器中自动连接所需的服务 @Controller @RequestMapping(value="/foo") public class FooController { @Autowired private FooService fooService; @Autowired private BarService barService; @Autowired private BazService bazServic

考虑以下两个选项:

选项#1:在控制器中自动连接所需的服务

@Controller
@RequestMapping(value="/foo")
public class FooController {
    @Autowired
    private FooService fooService;

    @Autowired
    private BarService barService;

    @Autowired
    private BazService bazService;

    @RequestMapping(method=RequestMethod.GET)
    public String getFoo(...) {
        Foo foo = fooService.getFooInstance(...);

        List<Foo> foos = fooService.getFooList(foo);
        List<Bar> bars = barService.getBarList(foo);
        Baz baz        = bazService.getBaz(foo);

        ...

        return "view/foo/index.jsp";
    }
}
@控制器
@请求映射(value=“/foo”)
公共类FooController{
@自动连线
私人餐饮服务;
@自动连线
私人酒吧服务;
@自动连线
私人服务;
@RequestMapping(method=RequestMethod.GET)
公共字符串getFoo(…){
Foo-Foo=fooService.getFooInstance(…);
listfoos=fooService.get傻瓜列表(foo);
列表栏=barService.getBarList(foo);
Baz-Baz=bazService.getBaz(foo);
...
返回“view/foo/index.jsp”;
}
}
选项2:特定服务中UoW的自动布线相关服务

@Controller
@RequestMapping(value="/foo")
public class FooController {
    @Autowired
    private FooService fooService;

    @RequestMapping(method=RequestMethod.GET)
    public String getFoo(...) {
        Foo foo = fooService.getFooInstance(...);

        FooDTO fooInfo = fooService.getFooAllInformation(foo);

        List<Foo> foos = fooInfo.getFoos();
        List<Bar> bars = fooInfo.getBars();
        Baz baz        = fooInfo.getBaz();
        ...

        return "view/foo/index.jsp";
    }
}


@Service
public class FooServiceImpl implements FooService {
    @Autowired
    private FooRepository fooRepository;

    @Autowired
    private BarService barService;

    @Autowired
    private BazService bazService;

    ...

    @Override
    @Transactional
    public FooDTO getFooAllInformation(Foo foo) {
        List<Foo> foos = getFooList(foo);
        List<Bar> bars = barService.getBarList(foo);
        Baz baz        = bazService.getBaz(foo);

        ...
    }
}
@控制器
@请求映射(value=“/foo”)
公共类FooController{
@自动连线
私人餐饮服务;
@RequestMapping(method=RequestMethod.GET)
公共字符串getFoo(…){
Foo-Foo=fooService.getFooInstance(…);
foodtofooinfo=fooService.getFooAllInformation(foo);
List foos=fooInfo.getFoos();
列表栏=fooInfo.getbar();
Baz Baz=fooInfo.getBaz();
...
返回“view/foo/index.jsp”;
}
}
@服务
公共类FooServiceImpl实现FooService{
@自动连线
私人食物储存库;
@自动连线
私人酒吧服务;
@自动连线
私人服务;
...
@凌驾
@交易的
公共食品至获取食品信息(Foo-Foo){
列表foos=get傻瓜列表(foo);
列表栏=barService.getBarList(foo);
Baz-Baz=bazService.getBaz(foo);
...
}
}

嗯,目前我正在使用选项1,一切正常。但我想知道这种方法是否足够好。它们中的任何一个比另一个有任何显著的优势吗?我应该提到的是,我知道服务的
插入部分(我在这里省略了该部分)有
@Transactional
。但是,仅仅读取数据又如何呢。

第二种选择更干净、更快、更安全。它基本上是使用门面模式

更干净,因为它将代码业务代码移到它所属的UI层之外的服务层中

更快是因为,由于所有事务都是在同一个事务中进行的,因此您将保存事务的开始和结束,并从事务缓存中获益(假设您使用ORM获取所需的数据)。当然,如果UI和服务层在独立的JVM上,速度会更快


更安全的原因是,由于所有内容都在同一事务中,因此每个服务都将从相同的一致性数据库“快照”中获取数据。在第一个选项中,您可以让第一个方法返回一个在调用第二个服务时不再存在的foo。当然,这取决于数据库的事务隔离级别,但它始终比在多个事务中执行更安全。

第二个选项更干净、更快、更安全。它基本上是使用门面模式

更干净,因为它将代码业务代码移到它所属的UI层之外的服务层中

更快是因为,由于所有事务都是在同一个事务中进行的,因此您将保存事务的开始和结束,并从事务缓存中获益(假设您使用ORM获取所需的数据)。当然,如果UI和服务层在独立的JVM上,速度会更快


更安全的原因是,由于所有内容都在同一事务中,因此每个服务都将从相同的一致性数据库“快照”中获取数据。在第一个选项中,您可以让第一个方法返回一个在调用第二个服务时不再存在的foo。当然,这取决于数据库的事务隔离级别,但它始终比在多个事务中执行安全。

重要的是,与事务相关的行为差异。使用#1回滚将不会像预期的那样工作。@atamanroman:同意,但由于所有这些方法都是从get开始的,所以我假设它们是只读方法,其中回滚并不重要。这就是为什么我坚持孤立而不是一致性。但当然,更重要的是将所有内容放在一个事务服务方法中,即修改数据库的方法。@JBNizet@atamanroman谢谢您的回答。我知道插入数据的情况。但现在这又给我提出了另一个问题
getFooAllInformation
是执行UoW的起点,当然它是事务性的。在其中调用的所有其他方法也应该是事务性的吗?(例如,
getBarList
getBaz
,…)它们将自动成为同一事务的一部分,因为该事务是在调用
getFooAllInformation()
时启动的。如果您计划从非事务性方法(例如,直接从表示层)调用它们,那么它们可能应该用@transactional,yes注释。@JBNizet您是对的。总而言之,1几乎总是个坏主意。我正在从事的一个大型遗留项目就是这样做的,这会导致大量的PITA,因为回滚只是部分的,并且会留下不一致的数据。与此相比,将所有业务代码放在UI中的问题要小一些。重要的是,与事务相关的行为存在差异。使用#1回滚将不会像预期的那样工作。@atamanroman:同意,但由于所有这些方法都是从get开始的,所以我假设它们是只读方法,其中回滚并不重要。这就是为什么我坚持孤立而不是一致性。但当然,将所有内容放在一个事务服务方法中更重要的是修改数据库的方法。@JBNizet@atamanroman