반응형
1일 1개념정리 24.08.09.금 ~
큰 결정에 큰 동기가 따르지 않을 때도 있다. 하지만 큰 결심이 따라야 이뤄낼 수 있다.
무조건 무조건 1일 1개의 개념 정리하기 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#14. Spring @OOOArgsConstructor
스프링에서 생성자를 처리하는 방법이 여러개 있다. 보통 OOOArgsConstructor 어노테이션을(Lombok 계열) 쓰는데, 오늘은 이것과 함께 Autowired, Builder에 대해서도 알아보자.
@Autowired
@Autowired는 의존성 주입을 위해 사용한다. 스프링 컨테이너가 관리하는 빈 중에서 해당하는 타입의 빈을 자동으로 주입해준다. 이 어노테이션은 필드, 메서드, 생성자 모두에 사용할 수 있다. Autowired는 다음과 같은 특징이 있다.
- 순환 참조 : 의존성 주입 시 순환 참조가 발생할 수 있는데, A클래스가 B클래스를, 다시 B가 A를 주입받으려고 하면 순환 참조가 발생하는데 생성자 주입을 사용하면 이런 문제를 컴파일 시점에 발견할 수 있다.
- Optional 주입 : 필드가 반드시 필요한 것이 아니고 선택적으로 주입하고 싶다면 @Autowired(required = false)로 설정할 수 있고 이러면 해당 빈이 존재하지 않아도 에러가 발생하지 않는다.
- @Autowired를 사용할 때 주입되는 빈이 스프링 컨텍스트에서 관리되고 있는지 확인해야 하는데, 잘못해서 의존성이 제대로 주입되지 않으면 NullPointerException이 발생한다.
public class MyService {
private final MyRepository repository;
// Optional 주입
@Autowired(required = false)
private MyRepository mymymyRepository;
// 생성자 주입
@Autowired
public MyService(MyRepository repository) {
this.repository = repository;
}
}
@NoArgsConstructor
- 파라미터가 없는 기본 생성자를 자동으로 생성하여 필드 초기화 없이 객체 생성이 가능하게 함
- 기본 생성자가 필수인 경우에 유용. 그러나 이렇게 생성하면 필드값이 모두 기본값으로 설정돼서 0, false, null 이런 값이 들어가있어서 당황할 수 있다.
- JPA 엔티티에서는 기본 생성자가 필요한데, JPA 엔티티에 기본 생성자를 추가할 때는 @NoArgsConstructor와 함께 protected를 사용하는 것이 권장된다.
- 클래스에 final 필드가 있으면 @NoArgsConstructor는 컴파일 에러를 발생시킨다. 왜냐면 final 필드를 초기화할 방법이 없기 때문인데, 이럴 땐 force=true 옵션을 써서 final 필드를 0 또는 null로 초기화할 수 있긴 하다. 물론 이게 또 다른 에러 발생시킬 수도 있다.
//@NoArgsConstructor(force = true)
@NoArgsConstructor
public class MyEntity {
private Long id;
private String name;
}
@AllArgsConstructor
- 클래스의 모든 필드를 파라미터로 가지는 생성자를 자동 생성해서 객체를 한 번에 초기화할 수 있다.
- 모든 필드를 인자로 받아야 해서 불필요한 필드 초기화로 메모리사용 등 효율성 떨어뜨린다.
- 생성자 파라미터의 순서는 클래스 필드 선언 순서에 따른다. 필드가 많아지면 생성자 호출 시 파라미터를 잘못된 순서로 전달할 위험이 있다.(잘못된 데이터 초기화 초래)
- 뭔소리냐면, @AllArgsConstructor쓰고 User u = new User(25, kwanghwi, abc@naver.com) 이렇게 했는데 알고보니 순서가 이름, 이메일, 나이였다면??? 내 이름이 25, 이메일이 kwanghwi ... 이렇게 초기화 되는 것이다.
- 그래서 이럴 땐 순서 신경쓰지 않아도 되는 @Builder를 쓰는 게 좋다.
- 생성자에서 모든 필드를 초기화하므로 final 필드의 불변성을 유지할 수 있다.
@AllArgsConstructor
public class MyEntity {
private Long id;
private String name;
}
@RequiredArgsConstructor
- final로 선언된 필드를 파라미터로 가지는 생성자를 생성하기 때문에 필요한 필드만을 인자로 받아 객체를 생성할 수 있음. 이를 통해 필요한 필드는 꼭 초기화하고, 반대로 불필요한 필드는 초기화 하지 않을 수 있음.
@RequiredArgsConstructor
public class MyEntity {
private final Long id; // final 유의
private String name;
}
@Builder
- 복잡한 객체 생성 시에 특히 유용하고, 선택적인 필드 초기화가 가능하고, 가독성이 높아진다. (아래 코드 예시)
- @Builder는 내부적으로 @AllArgsConstructor와 비슷하지만, 체이닝 방식으로 필드를 설정할 수 있다는 점이 다르다.
// 빌더 패턴을 사용한 객체 생성
User user = User.builder()
.name("kwanghwi")
.age(24)
.email("abc@naver.com")
.build();
정리
- 단순 생성자가 필요한 경우 : @NoArgsConstructor , @AllArgsConstructor
- 필수 필드만 초기화 : @RequiredArgsConstructor
- 유연한 객체 생성 : @Builder
반응형
'1일 1개념정리 (24년 8월~) > Spring' 카테고리의 다른 글
1일1개 (31) - mappedBy (다시 수정하기) (0) | 2024.09.10 |
---|---|
1일1개 (15) - 콩 너는 죽었다 (0) | 2024.08.24 |
1일1개 (12) - @Transactional (0) | 2024.08.20 |
1일1개 (11) - JDBC 발전 과정 (0) | 2024.08.19 |
1일1개 (10) - JDBC (0) | 2024.08.18 |