↩뒤로가기

막상 개발을 해보면, 대부분이 다 불변이다. 그래서 생성자에 final 키워드를 사용하게 된다.

그런데 생성자도 만들어야 하고, 주입 받은 값을 대입하는 코드도 만들어야 하고… 필드 주입처럼 더 편리하게 사용하는 방법은 없을까?

다음 코드를 최적화해보자

기존 코드

@Component
public class OrderServiceImpl implements OrderService{

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;

		@Autowired//생성자가 하나밖에 없으면 생략 가능
    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }

@Autowired를 생략

@Component
public class OrderServiceImpl implements OrderService{

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;

    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }

롬복 라이브러리가 제공하는 @RequiredArgsConstructor 기능을 사용하면 final 필드를 모아 생성자를 자동으로 만들어준다. (다음 코드에는 보이지 않지만 실제 호출 가능하다.)

build.gradle 수정

plugins {
	id 'java'
	id 'org.springframework.boot' version '2.7.8'
	id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}

group = 'hello'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

//lombok 설정 추가 시작
configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}
//lombok 설정 추가 끝

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter'

	//lombok 라이브러리 추가 시작
	compileOnly 'org.projectlombok:lombok'
	annotationProcessor 'org.projectlombok:lombok'
	testCompileOnly 'org.projectlombok:lombok'
	testAnnotationProcessor 'org.projectlombok:lombok'
	//lombok 라이브러리 추가 끝
	
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
	useJUnitPlatform()
}

<aside> 💡 File-Settings에서 다음 두 가지를 추가로 확인해야 한다.

  1. plugins 검색 → Lombok 플러그인 설치 확인
  2. Annotation Processors 검색 → Enable annotation processing 체크박스 활성화

</aside>

롬복 @annotation 활용 예시

package hello.core;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class HelloLombok {

    private String name;
    private int age;

    public static void main(String[] args) {
        HelloLombok helloLombok = new HelloLombok();
        helloLombok.setName("asdsda");

        String name = helloLombok.getName();
        System.out.println("helloLombok = " + helloLombok);
    }
}
// 별도의 getter, setter 등 메소드를 정의하지 않고도 애노테이션만으로 메소드 사용이 가능해진다.

기존 생성자에 롬복을 적용하면?

@Component
@RequiredArgsConstructor
//이 애노테이션은 아래 생성자를 똑같이 만들어준다. 즉 생성자랑 동시에 존재할 수 없다.
public class OrderServiceImpl implements OrderService{

//롬복은 final이 붙은 필드를 기준으로 생성자를 만들어준다.
    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;

/* 이건 이제 다 필요가 없다.
    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }
*/

최종 결과

@Component
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService{

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;