spring container, spring bean에 대해서 알아보자
spring container
- ApplicationContext 를 스프링 컨테이너라 한다.
- spring container는 @Configuration 이 붙은 AppConfig 를 설정(구성) 정보로 사용한다. 여기서 @Bean 이 라 적힌 메서드를 모두 호출해서 반환된 객체를 스프링 컨테이너에 등록한다. 이렇게 spring container 에 등록된 객체를 spring bean이라 한다.
- spring bean은 @Bean 이 붙은 메서드의 명을 spring bean의 이름으로 사용한다.
- spring container 는 설정 정보를 참고해서 의존관계를 주입(DI)한다.
//스프링 컨테이너 생성
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
- ac.getBeanDefinitionNames() : 스프링에 등록된 모든 빈 이름을 조회한다.
- ac.getBean() : 빈 이름으로 빈 객체(인스턴스)를 조회한다
- ac.getBean(beanName, type)
- ac.getBean( type )
- spring이 내부에서 사용하는 빈은 getRole() 로 구분할 수 있다.
- ROLE_APPLICATION : 일반적으로 사용자가 정의한 빈
- ROLE_INFRASTRUCTURE : 스프링이 내부에서 사용하는 빈
- ac.getBeansOfType() 을 사용하면 해당 타입의 모든 빈을 조회할 수 있다
- 부모 타입으로 조회하면, 자식 타입도 함께 조회한다.
- 모든 자바 객체의 최고 부모인 Object 타입으로 조회하면, 모든 스프링 빈을 조회한다.
BeanFactory와 ApplicationContext
BeanFactory
- 스프링 컨테이너의 최상위 인터페이스다.
- 스프링 빈을 관리하고 조회하는 역할을 담당한다.
- getBean() 을 제공한다.
ApplicationContext
- BeanFactory 기능을 모두 상속받아서 제공한다.
- ApplicationContext는 빈 관리기능 + 편리한 부가 기능을 제공한다.
스프링 빈 설정 메타 정보 - BeanDefinition
- BeanDefinition 을 빈 설정 메타정보라 한다.
- @Bean 각각 하나씩 메타 정보가 생성된다.
- spring container는 이 메타정보를 기반으로 스프링 빈을 생성한다.
singleton container
스프링 컨테이너는 싱글톤 패턴의 문제점을 해결하면서, 객체 인스턴스를 싱글톤(1개만 생성)으로 관리한다. 지금까지 우리가 학습한 스프링 빈이 바로 싱글톤으로 관리되는 빈이다.
@Configuration 을 붙이면 바이트코드를 조작하는 CGLIB 기술을 사용해서 싱글톤을 보장한다. (DI를 사용할때 이미 존재하는 bean의 경우 추가적으로 bean을 생성하지 않고 기존에 생성해놓은 bean을 사용해야 하므로)
@Bean
public MemberRepository memberRepository() {
if (memoryMemberRepository가 이미 스프링 컨테이너에 등록되어 있으면?) {
return 스프링 컨테이너에서 찾아서 반환;
} else { //스프링 컨테이너에 없으면
기존 로직을 호출해서 MemoryMemberRepository를 생성하고 스프링 컨테이너에 등록
return 반환
}
컴포넌트 스캔과 의존관계 자동 주입
스프링은 설정 정보가 없어도 자동으로 스프링 빈을 등록하는 컴포넌트 스캔이라는 기능을 제공한다. 또, 의존관계도 자동으로 주입하는 @Autowired 라는 기능도 제공한다.
의존관계 주입 방법
의존관계 주입은 크게 4가지 방법이 있다
- 생성자 주입 - 불변, 필수 의존관계에 사용(권장)
- 수정자 주입(setter 주입) - 선택, 변경 가능성이 있는 의존관계에 사용
- 필드 주입
- 일반 메서드 주입
생성자가 딱 1개만 있으면 @Autowired를 생략해도 자동 주입 된다. 물론 스프링 빈에만 해당한다 : @Autowired 의 기본 동작은 주입할 대상이 없으면 오류가 발생하는데, 주입할 대상이 없어도 동작하게 하려면 @Autowired(required = false) 로 지정하면 된다
Lombok
Lombok의 기능은 model 클래스나 Entity 같은 도메인 클래스 등에 반복되는 getter, setter, toString 등의 메소드를 자동으로 만들어주는 기능을 한다.
롬복 라이브러리가 제공하는 @RequiredArgsConstructor 기능을 사용하면 final이 붙은 필드를 모아서 생 성자를 자동으로 만들어준다.
조회 빈이 2개 이상일때
@Autowired 는 타입(Type)으로 조회한다 -> 조회 대상 빈이 2개 이상일 때 해결 방법
- @Autowired 필드 명 매칭
- @Qualifier @Qualifier끼리 매칭 빈 이름 매칭
- @Primary 사용
필드 명 매칭은 먼저 타입 매칭을 시도 하고 그 결과에 여러 빈이 있을 때 추가로 동작하는 기능이다
@Autowired 매칭 정리 1. 타입 매칭 2. 타입 매칭의 결과가 2개 이상일 때 필드 명, 파라미터 명으로 빈 이름 매칭
필드명을 빈 이름으로 변경
@Autowired private DiscountPolicy discountPolicy ->@Autowired private DiscountPolicy rateDiscountPolicy
@Qualifier
빈 등록시 @Qualifier를 붙여 준다
@Component
@Qualifier("mainDiscountPolicy")
public class RateDiscountPolicy implements DiscountPolicy {}
주입시에 @Qualifier를 붙여주고 등록한 이름을 적어준다.
@Autowired
public OrderServiceImpl(MemberRepository memberRepository, @Qualifier("mainDiscountPolicy") DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
@Primary
@Primary 는 우선순위를 정하는 방법이다. @Autowired 시에 여러 빈이 매칭되면 @Primary 가 우선권을 가진다.
출처
[지금 무료] 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 강의 - 인프런
스프링 입문자가 예제를 만들어가면서 스프링 웹 애플리케이션 개발 전반을 빠르게 학습할 수 있습니다., 스프링 학습 첫 길잡이! 개발 공부의 길을 잃지 않도록 도와드립니다. 📣 확인해주세
www.inflearn.com