@AllArgsConstructor는 모든 필드를 파라미터로 받는 생성자를 자동으로 생성해주는 lombok 어노테이션이다.
@NoArgsConstructor는 기본 생성자를 만들기 위한 lombok 어노테이션이다.
import lombok.AllArgsConstructor;
@AllArgsConstructor
public class Person {
private String name;
private int age;
}
를 하면
public Person(String name, int age) {
this.name = name;
this.age = age;
}
자동으로 생성되는 것이다.
하지만 기본 생성자는 생성되지 않는다.
그건 @NoArgsConstructor가 필요하다.
근데 이렇게 @AllArgsConstructor를 하게 되면
다른 곳에서 new 생성자를 이용해 아무 곳에서나 생성을 할 수 있게 된다. = 캡슐화가 전혀 되지 않는다.
access라는 옵션이 있다.
이 옵션은 NoArgsConstructor와 AllArgsConstructor 둘 다 해당한다.
@AllArgsConstructor(access = AccessLevel.PROTECTED)
로 쓸 수 있고
사용하는 예시로는 PRIVATE같은 경우
정적 팩토리를 사용해 객체를 생성할 때 주로 사용한다.
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class User {
private String id;
private String name;
public static User of(String id, String name) {
return new User(id, name);
}
}
spring에서 보통 사용하는 orm인 JPA에서는 프록시/리플렉션을 사용해서 객체를 생성하기 때문에 기본 생성자가 반드시 필요하다.
그럼으로 @AllArgsConstructor(access = PRIVATE)만 사용할 경우 에러가 날텐데 그럴땐
@Entity
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class User {
@Id
private String id;
private String name;
public static User create(String id, String name) {
return User.builder()
.id(id)
.name(name)
.build();
}
}
이런 식으로
@NoArgsConstructor(access = AccessLevel.PROTECTED)
기본 생성자를 PROTECTED로 만들어줌으로써 에러를 방지 시킬 수 있다.
사실 이 두 어노테이션은 Entity나 DTO에서 무분별하게 사용하는 경우가 많다. (물론 기본값인 PUBLIC이다)
필자는 두가지 방법을 선호한다.
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class UserDto {
private String name;
private int age;
public static UserDto of(String name, int age) {
return new UserDto(name, age);
}
}
정적 팩토리 메서드 패턴을 강제시켜 생성은 의도 있는 메서드를 통해서만 가능하게 한다.
두 번째로 순서때문에 오류가 나지 않도록 builder 패턴을 사용한다.
of와 to, create, from 등의 메서드를 자주 사용하는데
여기서 to와 from의 경계가 모호한데
to는 내부에서 변환할 때 from은 다른 객체를 받아서 본인의 객체를 만들 때라고 생각하면 편하다. (of와 from은 섞어 쓸 때도 있다)