주노 님의 블로그

[Spirng] 5. 스프링 빈과 의존관계 설정 본문

공부/Spring

[Spirng] 5. 스프링 빈과 의존관계 설정

juno0432 2024. 7. 28. 20:36

시작하기에 앞서

아래 내용은 김영한님의 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB접근기술에서 발췌한 내용입니다.

 

 

강의자료 일부를 발췌하는건 괜찮다고 하셨다.

무료강의로 지식을 공유해주신 김영한님께 다시한번 감사의 인사를 올리겠습니다

(_ _) (유료도 샀어요!)

 

스프링 빈을 등록하는 방법에는 두가지가 있다

 

1. 컴포넌트 스캔과 자동 의존관계 설정 

 

@Controller
public class MemberController
{

}

 

컨트롤러 어노테이션을 적용한다

스프링 컨테이너는 이 어노테이션이 있으면 객체로 생성해 스프링에 저장해둔다 (이 객체는 이하 스프링 빈 이라고함)

스프링 컨테이너는 빈의 생명주기를 관리한다.

 

@Autowired
public MemberController(MemberService memberService)
{
    this.memberService = memberService;
}

 

 

 

생성자에 autowired어노테이션을 지정하면

스프링은 아래와 연관된 객체를 스프링 컨테이너에서 찾아서 넣는다.(의존성 주입)

 

springProject.hello_spring.member_management.service.MemberService' that could not be found.

 

위와 같은 오류가 뜨게되는데

memberService가 스프링 빈으로 등록되지않아 실행시 찾을수 없다는 뜻이다

 

@Service
public class MemberService
{

 

memberService에 @Service 어노테이션을 붙이면

자동으로 스프링 빈으로지정되어 스프링 컨테이너가 관리하게된다

 

@Autowired
public MemberService(MemberRepository memberRepository) {
    this.memberRepository = memberRepository;
}

 

memberService도 의존성 주입을 받게되는데

 

@Repository
public class MemoryMemberRepository implements MemberRepository 

 

MemberRepository 구현체에 @Repository 어노테이션을 지정한다

 

위와 같은 방식을 컴포넌트 스캔방식이라고 하는데

왜 컴포넌트 스캔방식일까?

@Component어노테이션이 지정되어있으면 자동으로 스프링빈으로 등록된다

 

@Component
public @interface Service {
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";
}

 

Service의 인터페이스인데 service도 Component 어노테이션이 있는것을 볼 수 있다

위와 같은이유로 @Service 어노테이션을 지정해주면 Component를 지정해준것과 같다

 

위 어노테이션도 적용 범위가 있는데

 

@SpringBootApplication
public class HelloSpringApplication {

    public static void main(String[] args) {
       SpringApplication.run(HelloSpringApplication.class, args);
    }

}

 

프로젝트를 시작하는

즉 @SpringBootApplication 어노테이션이있는

패키지의 모든 하위패키지에서만 적용이된다

즉, HelloSpringApplication의 상위 패키지에 어노테이션을 달아도

컨테이너는 스프링빈으로 등록하지 않는다.

 

2. 자바 코드로 직접 스프링 빈 등록하기

기존에 만든 @Service, @Repository, @AutoWired를 삭제하고

 

SpringConfig를 만든다

 

@Configuration
public class SpringConfig
{
    //Bean 어노테이션을 적용하면 스프링 빈에 넣어준다.
    @Bean
    public MemberService memberService()
    {
        return new MemberService(memberRepository());
    }

    @Bean
    public MemberRepository memberRepository()
    {
        return new MemoryMemberRepository();
    }

}

 

@Configuration 어노테이션을 적용한다

 

의존성 주입의 세가지 방법이 있다

 

1. 생성자 주입

public MemberService(MemberRepository memberRepository) {
    this.memberRepository = memberRepository;
}

memberRepository는 생성자를 통해 들어오게된다

제일 권장하는 방식이다

애플리케이션이 로딩(조립)되는 시점에 한번 들어오고, 실행되는 동안에는 변경이 되지않는 불변객체가된다.

 

2. 

필드 주입

@Autowired private final MemberRepository memberRepository;

필드에서 바로 주입하는 방식이다

 

3.

setter주입

@Autowired
public void setMemberService(MemberService memberService)
{
    this.memberService = memberService;
}

 

setter를 통해 주입을 받을 수 있다

누군가가 memberController를 조회하려면 위 setter는 public으로 열려있어야한다

setMemberService는 중간에 바뀔 일이 없다

누군가가 열어보고 수정할수 있다는뜻.

하지만 중간에 바뀌어지면 문제가 발생할 수도 있음

 

실무에서는 정형화된 컨트롤러, 서비스, 리포지터리 같은 코드는 컴포넌트 스캔 방식을 사용한다.

정형화된 : 프로그램이 가동되는 중에 거의 잘 바뀌지 않는것들

정형화 되지 않거나, 상황에 따라 구현 클래스를 변경해야한다면, 설정을 통해 스프링 빈으로 등록한다.

>> config에서 설정값만 바꿔도 바로 변경될수 있다.