티스토리 뷰

컴포넌트 스캔 (의존관계 자동 주입)

  • @Component, @Autowired 어노테이션을 달아서 자동으로 Bean을 생성하고 의존관계 주입
  • 권장 사용처
    • 업무 로직 Bean
      - Controller, Service, Repository 등 보통 비즈니스 요구사항을 개발할 때 추가되거나 변경되는 로직
      - 유사한 패턴을 지니고 있어서 보통 문제가 발생해도 어떤 곳에서 문제가 발생했는지 명확히 파악 가능

 


 

수동 Bean 등록 (의존관계 수동 주입)

  • @Configuration 설정 정보에 @Bean을 적고, 객체를 생성하고, 주입할 대상을 일일히 적어줌
  • 권장 사용처
    • 기술 지원 Bean
      - 공통 관심사(AOP)를 처리할 때 주로 사용
      (DB 연결, 공통 로그 처리 등 업무 로직을 지원하기 위한 하부로직/공통 기술)
      - 업무 로직에 비해 수가 적고, 애플리케이션 전반에 걸쳐 광범위하게 영향을 미치기 때문에 가급적으로 수동 빈 등록을 통해 명확하게 들어내는 방향을 지향
    • 비즈니스 로직 중 다형성을 적극 활용해야하는 경우
      - 수동 Bean으로 등록하거나, 특정 패키지에 같이 묶어서 자동으로 검색되더라도 용도를 명확히 이해할 수 있도록 하는 것이 좋음

 

 


 

중복 등록과 충돌

  • 컴포넌트 스캔에 의해 자동으로 등록된 스프링 Bean끼리 이름이 같은 경우
    • ConflictingBeanDefinitionException 예외 발생
  • 수동 등록 Bean과 컴포넌트 스캔의 자동 등록 Bean이 서로 이름이 같은 경우
    • 수동 등록 Bean이 우선권을 가짐 → 수동Bean이 자동Bean을 오버라이딩
      - Overriding bean definition for bean 'memoryMemberRepository' with a different definition: replacing
    • 최근 스프링 부트에서는 에러가 떨어지도록 함
      - Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true
  • 최근 스프링 부트에서 정책이 바뀐 것처럼, 이런 상황을 의도하여 설계하는 것은 지양하자

 


 

컴포넌트 스캔 + 자동 의존관계 주입의 동작 과정

  1. @Component가 붙은 모든 클래스를 스프링 Bean으로 등록
    • 이때 스프링 Bean의 기본 이름은 클래스명을 사용하되, 맨 앞글자만 소문자 사용
    • MemberServiceImpl → memberServiceImpl 
    • Bean 이름을 직접 지정하고 싶으면, @Component("memberService2") 이런식으로 직접 부여
  2. @Autowired 의존관계 자동 주입
    • 스프링 컨테이너가 @Autowired로 지정된 생성자에 해당 Bean을 조회하여 주입함
    • 이때 기본 조회 전략은 타입이 같은 Bean이다 getBean(MemberRepository.class)처럼
      • (상속 관계) 부모 타입으로 조회하면, 자식 타입도 함께 조회되어 끌려나온다
    • 조회한 타입의 스프링 Bean이 여러 개라면, NoUniqueBeanDefinitionException 오류 발생
      • Bean을 수동으로 등록해서 문제를 해결해도 되지만, 아래 방법들도 있다 참고!
        - @Autowired 필드 명 매칭
        - @Qualifier @Qualifier끼리 매칭 빈 이름 매칭
        - @Primary 사용

 

TODO 정리 추가하기

* Bean Scope(HTTP request lifecycle과 맞추는)(@PostConstruct, @PreDestroy)

* proxy(의존관계 주입 시 빈 스코프가 다르면?) 

 

 


 

스프링 컨테이너 - 싱글톤

  • 스프링 컨테이너는 객체 인스턴스를 싱글톤으로 관리한다 (=싱글톤 레지스트리)(@Configuration)
  • 따라서 고객의 요청마다 객체를 생성하지 않고, 이미 만들어진 객체를 공유하여 효율적으로 재사용한다
    • 여러 클라이언트가 하나의 객체 인스턴스를 공유하므로, 싱글톤 객체를 stateful하게 설계하면 안된다
    • 언제나 stateless로!
      - 특정 클라이언트에 의존적인 필드가 있으면 X
      - 특정 클라이언트가 값을 변경할 수 있는 필드가 있으면 X
      - 가급적 읽기만 가능해야 함
      - 필드 대신에 자바에서 공유되지 않는, 지역변수, 파라미터, ThreadLocal 등을 사용해야 함
  • CGLIB : 스프링 Bean이 싱글톤이 되도록 보장하기 위해 클래스의 바이트코드를 조작하는 라이브러리
    • Bean 클래스를 상속받은 임의의 다른 클래스를 만들고, 그 클래스를 Bean으로 등록
    • 해당 임의의 클래스에서 스프링 컨테이너에 등록되어 있는지 체크하게끔 함
    • bean = class hello.core.AppConfig$$EnhancerBySpringCGLIB$$bd479d70
  • @Configuration(CGLIB 기술 사용)없이 @Bean만 사용하면, 싱글톤을 보장하지 않음

 

 

 

'Spring' 카테고리의 다른 글

JPA 영속성 컨텍스트  (0) 2022.04.28
Redisson 분산락  (0) 2022.04.27
OSIV  (0) 2022.04.24
JPA N+1문제  (0) 2022.04.23
JPA의 병합(merge)과 변경 감지(Dirty Checking) 차이점  (0) 2022.04.21
공지사항
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31