我在IntelliJ中的Sping Boot 应用程序上看到了多个在线代码,许多代码同时使用@AllArgsConstructor
和@NoArgsConstructor
,两者都是构造函数,但用途不同-
@AllArgsConstructor
生成一个构造函数,该构造函数需要带注解类中每个字段的参数@NoArgsConstructor
生成不带参数的构造函数
那么,为什么我们要在同一实体上同时使用这两种方法?在这种情况下,它们如何发挥作用?
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Entity
public class Product {
@Id
private int id;
private String name;
private String type;
}
2条答案
按热度按时间8yparm6h1#
这些是Lombok的注解。要理解为什么需要它,你必须理解事物内部是如何工作的。
JPA表示
它的规范说:"* JPA规范要求所有持久化类都有一个无参数构造函数。这个构造函数可以是公共的,也可以是受保护的。因为编译器会在没有定义其他构造函数时自动创建一个默认的无参数构造函数,所以只有定义构造函数的类才必须包含一个无参数构造函数。"
为了进一步理解,当它使用反射创建实体时,它使用 * Class. newInstance() 方法,该方法需要一个无参数构造函数来创建示例。
Spring最常用的依赖注入类型是
1.基于构造函数的注入
1.基于设定器的注入
构造函数注入和setter注入之间有许多关键的区别。
@NoArgsConstructor(force = true)
,否则所有final字段都用 * 0/false/null * 初始化。对于具有约束的字段,例如@NonNull
字段,不生成校验,所以要知道这些约束通常只有在这些字段被正确初始化之后才能满足。某些Java构造,例如Hibernate和服务提供者接口需要无参数构造函数。此注解主要用于与@Data
或生成注解的其他构造函数之一结合使用。@NonNull
的字段将导致对这些参数进行空值检查。结论:
zkure5ic2#
JPA specification要求所有持久化类(
@Entity
)都有一个无参数构造函数,无论是public还是protected(注意,在处理Hibernate等实现时,这并不一定是真的,请参见this answer)。这是必需的,因为JPA使用默认的构造函数方法,通过反射API创建bean类。实际上,如果你的类包含许多构造函数,那么JPA不知道调用哪一个,这就是为什么它使用反射通过它的无参数构造函数示例化类:
其等价于
new Product()
(Product.class
是 * 类字面量 *,如果在类路径中找不到类,则它可能在运行时失败),然后,一旦示例化,就使用字段设置器来处理它。然后,在Java中,默认构造函数(无参数构造函数)会自动为类生成,除非您定义了其他构造函数(只有在您没有提供任何其他构造函数时才会这样做)。
因此,由于编译器在没有定义其他构造函数时会自动创建一个默认的无参数构造函数,因此只有定义构造函数的类在框架(这里是JPA)需要时才必须包含无参数构造函数,这就是为什么在添加
@AllArgsConstructor
注解时需要添加@NoArgsConstructor
注解的原因。还要注意,您使用的是
@Data
,它捆绑了@RequiredArgsConstructor
的特性,@RequiredArgsConstructor
将为所有final
或@NonNull
注解字段生成构造函数(参见Lombok documentation)。因此,由于您只使用了非final的可空字段,即使您没有添加@NoArgsConstructor
注解,它也可能生成一个空构造函数。不过,我还没有测试最后一种情况。我知道当直接使用@RequiredArgsConstructor
和非final的可空字段时,它会生成一个空的构造函数,但是我不知道当使用@Data
时,它是否同样工作。@Data
还捆绑了@ToString
,因此您不需要再次添加它。如果我不需要所有捆绑的注解,我个人并不喜欢使用
@Data
,所以我通常只用途:因为我通常不使用
toString()
也不使用参数化构造函数。它可能更冗长,但对我更有意义。