使用带有@Service / @RestController注解的Java Records可以吗

问题描述 投票:0回答:2

我更喜欢将其作为记录,因为样板较少,但是会有问题吗?

IntelliJ 建议我将一个基本的 Java 类 @Service 变成这样:

@Service
public class LocationService {
    private final PlaceRepository placeRepository;

    @Autowired
    public LocationService(PlaceRepository placeRepository) {
        this.placeRepository = placeRepository;
    }

    public List<PlaceDto> findPlacesByRegionId(Long regionId){
        return placeRepository.findByRegionId(regionId).stream().map(place -> new PlaceDto(place.getId(), place.getName())).toList();
    }
} 

像这样进入Java记录@Service:

@Service
public record LocationService(PlaceRepository placeRepository) {
    public List<PlaceDto> findPlacesByRegionId(Long regionId) {
        return placeRepository.findByRegionId(regionId).stream().map(place -> new PlaceDto(place.getId(), place.getName())).toList();
    }
}
java spring spring-boot
2个回答
30
投票

你可以这样做,但是记录有 getter(尽管没有

get
前缀),而服务层不应该有。

此外,您的 Service Facade 公开了通常是

@Transactional
的公共方法。您不想将它们与没有人会使用的方法混合在一起。

此外,记录定义了

equals()
hashCode()
,服务类也不需要这些。

最后,记录和服务之间唯一的共同主题是所有字段通常都是

final
并且所有字段通常都通过构造函数传递。这没有太多共同点。因此,为此使用记录听起来是个坏主意。


14
投票

让我引用甲骨文人

JEP 395 说:

[Records] 是充当不可变的透明载体的类 数据。

因此,通过创建记录,您可以告诉编译器、您的同事, 整个世界都认为这种类型与数据有关。更确切地说, (浅)不可变且可透明访问的数据。那是 核心语义 - 其他一切都从这里开始。

如果此语义不适用于您要创建的类型,则 你不应该创建记录。如果你无论如何都这么做了(也许是被 没有样板的承诺或者因为您认为记录是 相当于 @Data/@Value 或数据类),你正在混淆你的 设计和它很有可能会回来咬你。所以 不要。

UPD。

我花了几分钟的时间来弄清楚你的陈述“IntelliJ 建议我像这样转换一个基本的 Java 类 @Service”的根本原因是什么。并发现以下讨论:https://youtrack.jetbrains.com/issue/IDEA-252036

从而:

  • 对 spring bean 使用记录绝对是一个坏主意:这样的 bean 不符合自动代理的条件,而且记录不是为这种情况设计的
  • 这很尴尬,但 JetBrains 确实误导了 CE 用户
© www.soinside.com 2019 - 2024. All rights reserved.