minOS

의존관계 자동 주입(1) - 다양한 의존관계 주입 방법 본문

TIL/김영한의 스프링 핵심 원리

의존관계 자동 주입(1) - 다양한 의존관계 주입 방법

minOE 2024. 4. 6. 16:02
728x90

1) 생성자 주입

- 이름 그대로 생성자를 통해서 의존관계를 주입 받는 방법
- @Autowired사용
- 특징
    1) 생성자 호출 시점에 딱 한번만 호출되는 것이 보장된다.
    2) 불변,필수 의존관계에  사용
@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;
        System.out.println("memberRepository = " + memberRepository); //테스트 용도
        System.out.println("discountPolicy = " + discountPolicy);
    }

 

 

2) 수정자 주입

- setter라 불리는 필드의 값을 변경하는 수정자 메서드를 통해서 의존관계를 주입하는 방법
- 특징
    1) 선택, 변경 가능성이 있는 의존관계에 사용
    2) 자바빈 프로피티 규약의 수정자 메서드 방식을 사용하는 방법
@Component
public class OrderServiceImpl implements OrderService{

    private  MemberRepository memberRepository ;
    private  DiscountPolicy discountPolicy;


    @Autowired
    public void setMemberRepository(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }
    @Autowired
    public void setDiscountPolicy(DiscountPolicy discountPolicy) {

    }

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


호출 순서 보기

@Component
public class OrderServiceImpl implements OrderService{

    private  MemberRepository memberRepository ;
    private  DiscountPolicy discountPolicy;


    @Autowired
    public void setMemberRepository(MemberRepository memberRepository) {
        System.out.println("memberRepository = " + memberRepository);
        this.memberRepository = memberRepository;
    }
    @Autowired
    public void setDiscountPolicy(DiscountPolicy discountPolicy) {
        System.out.println("discountPolicy = " + discountPolicy);
        this.discountPolicy = discountPolicy;

    }
//@Autowired 생략된 것임
    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        System.out.println("OrderServiceImpl");
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }

참고
@Autowired의 기본 동작은 주입할 대상이 없으면 오류 발생 -> 주입할 대상이 없어도 동작하게 하려면 @Autowired(required= false)로 설정해야한다.


참고

자바빈(JavaBean)은 자바 언어에서 재사용 가능한 소프트웨어 컴포넌트를 만들기 위한 규약입니다. 자바빈은 특정한 규칙에 따라 작성되어야 하며, 이를 자바빈 프로퍼티 규약(JavaBean Property Specification)이라고 합니다. 자바빈은 일반적으로 속성(프로퍼티)과 이벤트를 처리하는 메서드를 가지고 있습니다.

자바빈 프로퍼티 규약에 따르면 다음과 같은 요소들이 있습니다:

1. Private 멤버 변수: 속성값을 저장하기 위한 멤버 변수는 `private`으로 선언되어야 합니다.

2. Public Getter/Setter 메서드: 각 속성에 대해 getter와 setter 메서드가 있어야 합니다. Getter 메서드는 해당 속성의 값을 반환하고, Setter 메서드는 해당 속성의 값을 설정합니다. Getter 메서드는 `getPropertyName()` 형식이며, Setter 메서드는 `setPropertyName()` 형식입니다. 여기서 `PropertyName`은 해당 속성의 이름입니다. 이 메서드들은 일반적으로 `public`으로 선언됩니다.

예를 들어, Person 자바빈 클래스의 경우:

public class Person {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}


위의 예시에서 `Person` 클래스는 `name`과 `age` 두 개의 속성을 가지고 있습니다. 각 속성은 `private`으로 선언된 멤버 변수를 가지며, 해당 변수에 접근하기 위한 `getName()`, `setName()`, `getAge()`, `setAge()`의 getter와 setter 메서드를 가지고 있습니다. 이것이 자바빈 프로퍼티 규약을 따른 예시입니다.

 

3) 필드 주입

- 이름 그대로 필드에 바로 주입하는 방법
- 특징
   1) 코드가 간결해지지만 외부에서 변경이 불가능해서 테스트하기 힘들다는 단점이 있다.
   2) DI 프레임워크가 없으면 아무것도 할 수 없다.
   3) 사용하지 말자
         - 애플리케이션의 실제 코드와 관계없는 테스트 코드
         - 스프링 설정을 목적으로 하는 @Configuration같은 특별한 용도로 사용
@Component
public class OrderServiceImpl implements OrderService{

    @Autowired private  MemberRepository memberRepository ;
    @Autowired private  DiscountPolicy discountPolicy;

}​


 

 

4) 일반 메서드 주입

- 일반 메서드에의해 주입 받을 수 있다.
- 특징
     1) 한번에 여러 필드를 주입 받을 수 있다.
     2) 일반적으로 잘 사용하지 않는다.
@Component
public class OrderServiceImpl implements OrderService{

    private  MemberRepository memberRepository ;
    private DiscountPolicy discountPolicy;
    @Autowired
    public void init(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }
}​

 

 

주의사항

의존관계 자동 주입은 스프링 컨테이너가 관리하는 스프링 빈이어야 동작한다.

728x90