Beans
스프링 빈(Bean) : 스프링 컨테이너가 생성하고 생명주기를 관리하는 자바 객체
Bean은 스프링을 구성하는 핵심 요소로, 빈 정의 메타데이터(BeanDefinition)로 등록되고 컨테이너는 해당 정의에 따라 객체를 생성, 의존성 주입, 초기화, 소멸까지 관리한다.
핵심 구성 요소
Section titled “핵심 구성 요소”- class
- 빈으로 등록할 Java 클래스
- 스프링 컨테이너에 의해 객체로 생성 및 관리되어 클래스의 인스턴스를 Bean으로 사용
- id
- 컨테이너에서 빈을 식별하기 위한 고유 식별자
- 클래스명을 decapitalize한 이름을 기본으로 부여하며, 명시적으로 지정 가능
- scope
- 빈 인스턴스의 생존 범위 정의
- 기본값 singleton
- constructor-arguments
- Bean을 생성할 때 생성자에 전달할 인자들을 정의
- Bean을 초기화하는 데 사용
- property
- Bean을 생성할 때 setter를 통해 전달할 인자들을 정의
- 기타 메타데이터
- initMethod, destroyMethod, lazyInit, primary, autowireCandidate, dependsOn, description 등
스프링 빈 등록 방법
Section titled “스프링 빈 등록 방법”1. 컴포넌트 스캔
Section titled “1. 컴포넌트 스캔”컴포넌트 스캔으로 어노테이션이 부여된 클래스를 자동 탐지하여 빈으로 등록한다.
- 사용 어노테이션:
@Component와 특화 어노테이션(@Controller,@Service,@Repository, 등) - 탐색 범위:
@ComponentScan의basePackages,basePackageClasses,includeFilters,excludeFilters로 제어 - 이름 규칙: 기본은 클래스명 decapitalize. @Component(“customName”)로 지정 가능
의존성 주입은 방법으론 여러 가지가 있는데, 그 중 생성자 주입 방법을 권장하고 있다.(단일 생성자일 경우 @Autowired 생략 가능)
@Servicepublic class MemberService {
private final MemberRepository memberRepository;
@Autowired // 생략 가능 public MemberService(MemberRepository memberRepository) { this.memberRepository = memberRepository; }}
@Repositorypublic class MemoryMemberRepository implements MemberRepository {
}2. 자바 설정(@Configuration + @Bean)
Section titled “2. 자바 설정(@Configuration + @Bean)”정형화 되지 않은 코드거나, 상황에 따라 구현 클래스를 변경해야하는 경우 사용한다.
@Configurationpublic class SpringConfig {
@Bean public MemberService memberService() { return new MemberService(memberRepository()); }
@Bean public MemberRepository memberRepository() { return new MemoryMemberRepository(); }}@Configuration에 두 가지 속성이 존재하는데, 각 역할은 다음과 같다.
value:@Configuration선언된 클래스의 이름을 지정proxyBeanMethods: 스프링이 관리하는 빈을 참조할 때 프록시를 사용하여 싱글톤 보장(기본값true)- 직접 생성한 객체를 사용하는 것이 아닌,
CGLIB에 의해 생성된 프록시 객체를 사용하여 싱글톤 보장
- 직접 생성한 객체를 사용하는 것이 아닌,
빈 생명주기
Section titled “빈 생명주기”스프링 빈은 생성 - 의존관계 주입 단계를 거쳐 사용할 수 있는 상태가 되며, 스프링 빈의 대략적인 이벤트 라이프 사이클은 아래와 같다.
- 스프링 컨테이너 생성
- 스프링 빈 생성 및 등록
Bean으로 등록할 수 있는Annotation및Configuration을 읽어 IoC 컨테이너 안에Bean으로 등록- 의존 관계 주입 전 객체 생성 과정 수행(Field/Setter 주입의 경우에만)
- 생성자 주입: 객체의 생성과 의존관계 주입이 동시에 발생
- Setter/Field 주입: 객체 생성 -> 의존 관계 주입 단계 분리
- 의존 관계 주입
- 초기화 콜백
- 빈이 생성되고, 빈의 의존관계 주입이 완료된 후 호출
- 런타임 사용
- 실제 애플리케이션(빈) 동작 단계
- 소멸 전 콜백
- 빈이 소멸되기 직전에 호출
- 스프링 종료
빈 생명주기(초기화/소멸) 콜백
Section titled “빈 생명주기(초기화/소멸) 콜백”빈은 시작 및 종료 시점에 추가적인 콜백 작업을 수행할 수 있으며, 아래 세 가지 방법을 제공한다.(실행되는 순서는 아래 번호 순서대로 실행)
1. @PostConstruct, @PreDestroy 애노테이션
Section titled “1. @PostConstruct, @PreDestroy 애노테이션”- @PostConstruct: 의존관계 주입이 끝나면 호출
- @PreDestroy: 빈이 종료될 때 호출
public class Example { // ...
@PostConstruct public void init() { action(); }
@PreDestroy public void close() { exit(); }}- 최신 스프링에서 가장 권장하는 방법
javax.annotation.PostConstruct인 자바 표준 기술- 컴포넌트 스캔과 궁합이 좋음
- 외부 라이브러리에는 적용 불가능 -> 이 경우
@Bean의initMethod,destroyMethod를 사용
2. 인터페이스(InitializingBean, DisposableBean)
Section titled “2. 인터페이스(InitializingBean, DisposableBean)”InitializingBeanInafterPropertiesSet(): 의존관계 주입이 끝나면 호출DisposableBeanIndestroy(): 빈이 종료될 때 호출
public class Example implements InitializingBean, DisposableBean { // ...
@Override public void afterPropertiesSet() throws Exception { action(); }
@Override public void destroy() throws Exception { exit(); }}- 스프링 전용 인터페이스에 의존
- 초기화, 소멸 메서드의 이름 변경 불가
- 코드를 고칠 수 없는 외부 라이브러리에 적용 불가
3. 설정 정보에 초기화 메서드, 종료 메서드 지정
Section titled “3. 설정 정보에 초기화 메서드, 종료 메서드 지정”@Bean(initMethod = "init", destroyMethod = "close")초기화/소멸 메서드 지정
public class Example { // ...
public void init() { action(); }
public void close() { exit(); }}
@Configurationpublic class AppConfig {
@Bean(initMethod = "init", destroyMethod = "close") public Example example() { return new Example(); }}- 메서드 이름 자유롭게 설정 가능
- 스프링 빈이 스프링 코드에 의존하지 않음
- 설정 정보를 사용하기 때문에 코드를 고칠 수 없는 외부 라이브러리에도 초기화, 종료 메서드 적용 가능
- 종료 메서드 추론 기능
@Bean의destroyMethod속성에는 아무것도 지정하지 않으면 추론 기능이 동작close,shutdown같은 일반적으로 많이 사용하는 종료 메서드를 자동으로 호출- 추론 기능을 막기 위해서
destroyMethod=""로 지정 할 수 있음
빈이 존재할 수 있는 범위를 뜻하며, 스프링 빈이 기본적으로 싱글톤 스코프로 생성되기 때문에 보통 스프링 컨테이너의 시작과 종료 시점과 같으며 크게 세 가지 스코프를 지원한다.
- 싱글톤(Default): 스프링 컨테이너의 시작과 종료 시점에 생성되고 소멸하는 가장 넓은 범위의 스코프, 가장 많이 사용되는 스코프
- 프로토타입: 스프링 컨테이너가 빈의 생성과 의존 관계 주입까지만 관여하고 더는 관리하지 않는 스코프
- 웹 관련 스코프
- request: 웹 요청 하나가 들어오고 나갈 때 까지 유지되는 스코프
- session: 웹 Session과 동일한 생명주기를 가지는 스코프
- application: 서블릿 컨텍스트와 동일한 생명주기를 가지는 스코프
프로토타입 스코프
Section titled “프로토타입 스코프”싱글톤 스코프는 스프링 컨테이너에서 항상 같은 인스턴스의 스프링 빈을 반환하지만, 스코프의 빈은 스프링 컨테이너에 요청할 때마다 새로 인스턴스를 생성하여 반환한다.
- 싱글톤 빈 / 프로토타입 빈 비교
| 싱글톤 빈 | 프로토타입 빈 |
|---|---|
| 싱글톤 스코프 빈을 스프링 컨테이너에 요청 | 프로토타입 스코프 빈을 스프링 컨테이너에 요청 |
| (요청 한 빈이 이미 생성되어 있는 상태) | 요청 온 시점에 프로토타입 빈을 생성하고 의존 관계 주입 |
| 스프링 컨테이너가 관리하고 있는 빈 반환 | 생성한 빈을 반환 |
| 같은 요청이 와도 계속 같은 인스턴스의 스프링 빈 반환 | 같은 요청이 오면 계속 새로운 인스턴스의 스프링 빈 반환 |
프로토타입 빈의 특징을 정리하면 다음과 같다.
- 스프링 컨테이너에 요청할 때 마다 새로운 인스턴스를 생성
- 스프링 컨테이너는 프로토타입 스코프 빈을
생성/의존관계 주입/초기화까지만 처리 - 생성 및 초기화까지만 처리하기 때문에
@PreDestroy같은 종료 메서드도 호출하지 않음 - 프로토타입 빈은 프로토타입 빈을 조회한 클라이언트가 관리
- 여러 빈에서 같은 프로토타입 빈을 주입 받으면, 주입 받은 모든 빈은 각자 다른 인스턴스를 사용(하나의 빈에선 계속 같은 프로토타입 빈을 가짐)