본문 바로가기

학원/복기

[Spring] Lombok 라이브러리

https://mvnrepository.com/

사이트에서 

 

 

 

복사해서 pom.xml 파일에 붙여넣는다.

 

 

라이브러리에 추가된 것을 확인할 수 있다


 

Lombok 라이브러리

 

Lombok 라이브러리는 클래스 작성에 필요한 메소드를 자동으로 생성하여 제공하는 기능의 라이브러리이다.

 

 


 

Lombok 라이브러리가 제공해주는 어노테이션 종류에 대해 알아보자

 

@NoArgsConstructor

  • @NoArgsConstructor은 매개변수가 없는 생성자를 자동 생성하여 제공하는 어노테이션이다.

 

@AllArgsConstructor

  • @AllArgsConstructor은 매개변수가 존재하는 생성자를 자동으로 생성하는 어노테이션이다.
  • 모든 필드에 초기값을 저장할 수 있는 매개변수가 있는 생성자를 생성한다. 

 

@RequiredArgsConstructor

  • @RequiredArgsConstructor은 매개변수가 있는 생성자를 자동으로 생성하는 어노테이션이다.
  • fianl 제한자를 사용하여 선언된 필드에 초기값을 저장할 수 있는 매개변수가 있는 생성자를 생성한다.
  • @NoArgsConstructor 어노테이션과 같이 사용하는 것이 불가능하다. 

 

 

@Setter

  • @Setter은 클래스에 선언된 모든 필드에 대한 Setter 메소드를 자동으로 생성하여 제공하는 어노테이션이다.
  • 필드에 @Setter을 사용하면 해당 필드에 대한 Setter 메소드를 자동으로 생성하여 제공한다. 

 

@Getter

  • @Getter은 클래스에 선언된 모든 필드에 대한 Getter 메소드를 자동으로 생성하여 제공하는 어노테이션이다.
  • 필드에 @Getter을 사용하면 해당 필드에 대한 Getter 메소드만을 자동으로 생성하여 제공한다.

 

@ToString

  • @ToString은 클래스에 toString() 메소드를 자동 생성하여 제공하는 어노테이션이다. 
  • 클래스에 선언된 모든 필드값을 문자열로 반환하는 기능을 제공해준다. 

 

@Data

  • @Data은 기본 생성자, Setter() 메소드, Getter() 메소드, toString() 메소드,  equals() 메소드, hashCode() 메소드를 자동 생성해서 제공해주는 어노테이션이다.

@Builder

  • @Builder은 Builder 클래스를 자동 생성하여 제공하는 어노테이션이다.
  •  Builder 클래스 : 객체 생성시 객체 필드에 필요한 값을 저장하기 위한 메소드를 제공하는 클래스
  • 생성자보다 가독성이 좋으며 필드의 순서에 상관없이 초기화 작업이 편리하다.
  • 매개변수의 생성자에 @Builder을 사용하면 생성자 매개변수로 초기화 처리하기 위한 필드에만 값을 저장할 수 있는 기능을 제공한다. 
  • 주로 Test 프로그램을 만들 때 많이 사용한다. 

 

@Slf4j

  • @Slf4j은 로그 이벤트를 발생하는 Logger 객체가 저장된 필드(log)를 자동으로 생성하여 제공하는 어노테이션이다.

 


예시)

package xyz.itwill05.lombok;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;

//어노테이션의 순서는 중요하지 않음
@AllArgsConstructor
@Data
@Builder
public class Member {
	private String id;
	private String name;
	private String email;
}

 

 

package xyz.itwill05.lombok;

public class MemberApp {
	public static void main(String[] args) {
		Member member1=new Member("abc123", "홍길동", "abc@itwill.xyz");

		System.out.println("아이디 = "+member1.getId());//아이디 = abc123
		System.out.println("이름 = "+member1.getName());//이름 = 홍길동
		System.out.println("이메일 = "+member1.getEmail());//이메일 = abc@itwill.xyz
		System.out.println("=======================================================");
		//Member 클래스로 생성된 참조변수를 출력할 경우 Member 클래스의 toString() 메소드 자동 호출
		System.out.println(member1);//Member(id=abc123, name=홍길동, email=abc@itwill.xyz)
	}
}

 

 

클래스명.builder()

  • 클래스 내부에 작성된 Builder 클래스로 객체를 생성하여 반환하는 메소드
  • Builder 객체로 필드명과 같은 이름의 메소드를 호출하여 필드값을 변경한다.
  • Builder.build() 메소드를 호출하면 클래스로 객체를 생성해 반환해준다. 

 

package xyz.itwill05.lombok;

public class MemberApp {
	public static void main(String[] args) {
		Member member2=Member.builder()
				.id("xyz789")
				.name("임꺽정")
				.email("xyz@itwill.xyz")
				.build();
		
		System.out.println(member2);//Member(id=xyz789, name=임꺽정, email=xyz@itwill.xyz)
	}
}

 

 

 

 


[05-5_diAnnotation.xml]

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
	<!--  xyz.itwill05.lombok 패키지 내에 있는 클래스들을 스캔하여 스프링 빈으로 등록하도록 설정 -->
    <context:component-scan base-package="xyz.itwill05.lombok"/>

</beans>

 

 

[MemberDAO] / [MemberDAOImpl]

package xyz.itwill05.lombok;

//MemberDAOImpl이 상속받을 인터페이스
public interface MemberDAO {
	int insertMember(Member member);
	int updateMember(Member member);
	int deleteMember(String id);
	Member selectMember(String id);
	List<Member> selectMemberList();
}

//package xyz.itwill05.lombok;


@Slf4j
//스프링 빈으로 등록
@Repository
public class MemberDAOImpl implements MemberDAO {
	public MemberDAOImpl() {
		log.info("MemberDAOImpl 클래스의 기본 생성자 호출");
	}
	
	@Override
	public int insertMember(Member member) {
		log.info("MemberDAOImpl 클래스의 insertMember() 메소드 호출");
		return 0;
	}
	
	@Override
	public int updateMember(Member member) {
		log.info("MemberDAOImpl 클래스의 updateMember() 메소드 호출");
		return 0;
	}
	
	@Override
	public int deleteMember(String id) {
		log.info("MemberDAOImpl 클래스의 deleteMember() 메소드 호출");
		return 0;
	}
	
	@Override
	public Member selectMember(String id) {
		log.info("MemberDAOImpl 클래스의 selectMember() 메소드 호출");
		return null;
	}
	
	@Override
	public List<Member> selectMemberList() {
		log.info("MemberDAOImpl 클래스의 selectMemberList() 메소드 호출");
		return null;
	}
}

 

[MemberService] / [MemberServiceImpl]

package xyz.itwill05.lombok;

//MemberServiceImple이 상속받을 인터페이스
public interface MemberService {
	void addMember(Member member);
	void modifyMember(Member member);
	void removeMember(String id);
	Member getMember(String id);
	List<Member> getMemberList();
}



@Slf4j
//스프링 빈으로 등록 - 빈 네임 변경 
@Service("MemberService")
public class MemberServiceImpl implements MemberService {
	@Autowired
	private MemberDAO memberDAO;

	@Override
	public void addMember(Member member) {
		log.info("MemberServiceImpl 클래스의 기본 생성자 호출");
		memberDAO.insertMember(member);
	}

	@Override
	public void modifyMember(Member member) {
		log.info("MemberServiceImpl 클래스의 modifyMember() 메소드 호출");
		memberDAO.updateMember(member);
	}

	@Override
	public void removeMember(String id) {
		log.info("MemberServiceImpl 클래스의 removeMember() 메소드 호출");
		memberDAO.deleteMember(id);
	}

	@Override
	public Member getMember(String id) {
		log.info("MemberServiceImpl 클래스의 getMember() 메소드 호출");
		memberDAO.selectMember(id);
		return null;
	}

	@Override
	public List<Member> getMemberList() {
		log.info("MemberServiceImpl 클래스의 getMemberList() 메소드 호출");
		memberDAO.selectMemberList();
		return null;
	}
}

 

필드에 @Autowired 어노테이션을 사용하여 의존성을 주입했다. (필드 레벨의 의존성 주입)

가장 보편적인 의존성 주입 방법이지만 순환 참조시 에러가 발생되지 않아 StackOverflow 발생 가능성이 있어 권장하는 방법은 아니다.

 

필드에 대한 Setter 메소드에 @Autowired 어노테이션을 사용하여 의존성을 주입하는 것도 가능하다. (Setter 레벨의 의존성 주입)

@Autowired
public void setMemberDAO(MemberDAO memberDAO) {
	this.memberDAO = memberDAO;
}

 

하지만 Setter 메소드의 접근 제한자가 [public]인 경우 Setter 메소드를 직접 호출하여 의존관계가 바뀔 수 있기 때문에 마찬가지로 권장하지 않는다.

 

 

매개변수로 전달받은 객체로 필드에 의존성을 주입하는 생성자에 Autowired 어노테이션을 사용하여 의존성을 주입하는 것도 가능하다. (Consturctor 레벨의 의존성 주입)

@Autowired
public MemberServiceimpl(MemberDAO memberDAO) {
	this.memberDAO=memberDAO;
	log.info("MemberServiceimpl 클래스의 매개변수가 선언된 생성자 호출");
}

 

Spring 프레임 워크에서는 순환 참조 방지를 위해 생성자를 이용한 의존성 주입을 가장 권장한다.

 

 

기본 생성자가 없고, 매개변수가 선언된 생성자만 작성한 경우 @Autowired 생략이 가능하다.

/*
public MemberServiceimpl() {
	log.info("MemberServiceimpl 클래스의 기본 생성자 호출");
}
*/	
	
@Autowired
public MemberServiceimpl(MemberDAO memberDAO) {
	this.memberDAO=memberDAO;
	log.info("MemberServiceimpl 클래스의 매개변수가 선언된 생성자 호출");
}

 

[MemberAnnotationApp] 에서 main 메소드 실행 

package xyz.itwill05.lombok;

public class MemberAnnotationApp {
	public static void main(String[] args) {
		System.out.println("=============== Spring Container 초기화 전 ===============");
		ApplicationContext context=new ClassPathXmlApplicationContext("05-5_diAnnotation.xml");
		System.out.println("=============== Spring Container 초기화 후 ===============");
		MemberService service=context.getBean("MemberService", MemberService.class);
		
		service.addMember(null);
		service.modifyMember(null);
		service.removeMember(null);
		service.getMember(null);
		service.getMemberList();
		System.out.println("==========================================================");
		((ClassPathXmlApplicationContext)context).close();			
	}
}

 


 

필드가 여러개인 경우에는 @RequiredArgsConstructor 를 사용해 생성자를 만들어주면 된다.

 

 @RequiredArgsConstructor : final 제한자를 사용하여 작성된 필드에 대한 초기화 설정이 가능한 생성자를 생성하는 어노테이션 

 

final 제한자 대신 @NonNull 어노테이션을 사용한 필드에 대한 생성자를 생성해도 된다.

@Slf4j
@RequiredArgsConstructor
@Service("memberService")
public class MemberServiceimpl implements MemberService {
	private final MemberDAO memberDAO;
    
   	//fianl 대신 @NonNull 사용 가능
    	//@NonNull private MemberDAO memberDAO;
    	...
}