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

Rob*_*gor 21 java spring spring-boot

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

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();
    }
} 
Run Code Online (Sandbox Code Playgroud)

像这样的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();
    }
}
Run Code Online (Sandbox Code Playgroud)

Sta*_*sev 29

你可以这样做,但记录有吸气剂(没有get前缀)。哪个服务层不应该有。您的服务门面公开了通常也是公共的方法@Transactional,您不想将它们与没有人会使用的方法混合在一起。

此外,记录定义了equals()服务hashCode()类也不需要的内容。

最后,记录和服务之间唯一的共同主题是所有字段final通常都是通过构造函数传递的。这没有太多共同点。因此,为此使用记录听起来是个坏主意。


And*_*lov 13

让我引用Oracle 人的话:

JEP 395 说:

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

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

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

UPD。

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

从而:

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