컨테이너 설정/애너테이션

박채은·2022년 12월 12일
0

Spring

목록 보기
8/35
public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(DependencyConfig.class); // (1)
    MyService myService = ctx.getBean(MyService.class);// (2)
    myService.doStuff();
}
ApplicationContext ctx = new AnnotationConfigApplicationContext(DependencyConfig.class);
  • ACAC를 사용하여 스프링 컨테이너를 인스턴스화한다.
  • DependencyConfig 클래스를 인자로 받고 있다.
    • 인자로 받는 해당 클래스를 설정 클래스(Config Class)라고 한다.
    • 설정 클래스는 해당 애너테이션이 달린 클래스이다.
      • @Configuration
      • @Component

@Configuration

  • Config 클래스로 설정해줌 = 스프링 설정 정보로 만든다.

    • 해당 클래스가 BeanDefinition의 소스임을 나타냄
  • @Configuration 클래스 자체가 BeanDefinition에 등록됨

    • @Configuration 내부에 @Component이 정의되어 있기 때문에
  • 클래스 내에 선언된 모든 @Bean 메서드도 BeanDefinition에 등록

  • 외부 라이브러리 또는 내장 클래스를 Bean으로 등록하고자 할 경우에 사용(개발자가 직접 제어가 불가능한 클래스)


@Bean

  • 메서드 레벌 애너테이션
  • @Bean은 @Configuration나 @Component가 붙은 클래스의 메서드에서 사용할 수 있다.
  • 해당 메소드를 BeanDefinition에 등록함
  • Bean 객체의 이름 = 메소드의 이름
    • 개발자가 직접 이름을 부여할 수도 있다.
      ex) @Bean(name="MemberRepository")
  • Bean이 생성되면, 의존 관계를 설정한다.

@Component

  • 해당 클래스를 Bean 정의로 등록
  • 개발자가 직접 작성한 클래스를 Bean으로 등록하고자 할 경우 사용

@ComponentScan

  • @Component 및 streotype(@Service, @Repository, @Controller) 애너테이션이 부여된 클래스를 스캔하여 자동으로 Bean으로 등록해주는 역할을 한다.
  • 이전까지는 Bean을 등록할 때, @Bean을 통해서 설정 정보에 등록할 Bean들을 직접 작성했다. 하지만 하나씩 작성해서 등록하게 되면, 정보가 누락되는 등 문제가 발생할 수 있다.

  • @ComponentScan을 Config 클래스에 붙여주면, @Component가 붙은 모든 클래스를 Bean으로 등록해주기 때문에 편리하다.


@ComponentScan의 대상

  • @Component
  • @Controller & @RestController
  • @Service: 비즈니스 로직에서 사용
  • @Repository: 스프링 데이터 접근 계층에서 사용
  • @Configuration: 스프링 설정 정보에서 사용

🚨 주의 🚨

@ComponentScan을 사용할 때, @Configuration이 붙은 클래스도 자동으로 빈으로 등록된다.

  • @Configuration 내부에 @Component 애너테이션이 있기 때문에

  • @ComponentScan + @Component@Configuration + @Bean을 혼용해서 사용하지 말자!

  • 기존에 작성한 설정 파일에 @Configuration가 붙어있다면, 충돌이 일어나 문제가 발생할 수 있다.

    • @Configuration 애너테이션을 제거하거나 아래 코드를 추가해주자.

      @ComponentScan(excludeFilters = @Filter(type = FilterType.ANNOTATION, classes = Configuration.class))


@Autowired

  • @ComponentScan + @Component만 사용했을 때에 설정 정보(Config 클래스)에 어떤 의존 객체를 주입할지 명시해주지 않기 때문에 의존 주입이 필요한 생성자 부분에 @Autowired를 통해 의존 관계 주입이 필요합니다.

  • 의존성 주입 시에, 설정 정보를 정의하는 대신 의존관계 자동 주입을 해준다.

@Component
public class MemberService {
  private final MemberRepository memberRepository;
  
  public MemberService(MemberRepository memberRepository) {
    this.memberRepository = memberRepository;
  }
}

위와 같이, 의존성 주입이 필요한 경우에 XML 파일이나 설정 정보(Config 클래스)를 정의한다.

@Configuration
public class Config {
    @Bean
    public MemberService memberService() {
        return new MemberService(memberRepository());
    }
    @Bean
    public MemberRepository memberRepository() {
        return new MemberRepository();
    }
}

하지만, @Autowired를 사용하면 굳이 설정 정보를 작성하지 않아도 자동으로 의존성 주입을 실행해준다.

@Component
public class MemberService {
  private final MemberRepository memberRepository;
  
  @Autowired
  public MemberService(MemberRepository memberRepository) {
    this.memberRepository = memberRepository;
  }
}
  • 스프링에서 Bean 인스턴스가 생성된 이후 @Autowired를 설정한 메서드가 자동으로 호출되고, 인스턴스가 자동으로 주입된다.

  • Bean이 하나의 생성자만을 가질 경우에, @Autowired는 자동으로 삽입되기 때문에 작성하지 않아도 된다.

참고 - @Autowired


basePackages

  • 탐색할 패키지의 시작 위치를 지정하고, 해당 패키지부터 하위 패키지 모두 탐색한다.

  • @ComponentScan()의 매개변수로 basePackages = “시작 위치”를 작성한다.

  • 지정하지 않으면, @ComponentScan이 붙은 설정 정보 클래스의 패키지가 시작 위치가 된다.

    • 설정 정보 클래스(Config 클래스)를 프로젝트 최상단에 두는 것이 가장 편하다.
  • 스프링 부트를 사용한다면, @SpringBootApplication을 프로젝트 시작 루트 위치에 두자!

    • @SpringBootApplication에 @ComponentScan이 들어있기 때문에 따로 basePackages를 설정할 필요없다.

Configuration/Bean/ComponentScan/Component

@Component + @ComponentScan@Configuration + @Bean으로 나누어서 사용할 수 있다.

Q) 왜 굳이 나누었을까?
A) @Bean과 @Component의 용도가 다르기 때문에!

@Bean메서드 영역에 올라가는 애노테이션으로, 해당 메서드에서 반환되는 리턴값을 Bean으로 등록한다.

@Component클래스에 붙이는 애노테이션으로, 이 클래스에 Bean이 담겨져 있다는 것을 알려준다. 런타임 시에, 스프링이 ComponentScan을 해서 자동으로 Bean을 찾고 등록한다.

빈은 메소드 레벨에서, 컴포넌트는 클래스 레벨에서 사용됨

@Component + @ComponentScan - 개발자가 직접 작성한 클래스를 Bean 등록하고자 할 경우 사용

@Configuration + @Bean - 개발자가 컨트롤이 불가능한 외부 라이브러리 또는 내장 클래스를 Bean으로 등록하고자 할 경우 사용


[참고]
https://lasbe.tistory.com/111
https://hyune-c.tistory.com/entry/Component-vs-Configuration
https://yhmane.tistory.com/129

0개의 댓글