SpringBoot #1.3 - DI
Dependancy Injection(DI), Circular Dependency, 컴포넌트 스캔, Autowired, Beans Scope, Life Cycle
DI (Dependency Injection)
- IoC 만드는 방법 중 하나
- 객체를 주입받는 생성자 / setter 주입 패턴
- 구현 패턴
- 전략패턴
- 서비스 로케이터 패턴
- 팩토리 패턴
- 의존관계 주입 패턴
- Spring에서는 IoC 컨테이너인 AppConfiguration 에서 Bean 객체를 생성하고, 전달해서 DI 적용
Circular Dependency (순환참조)
- A → B & B → A 의존관계 형성 시 발생
BeanCurrentlyInCreationException
발생
class objectA {
private final objectB b;
objectA (objectB b) {
this.b = b;
}
}
class objectB {
private final objectA a;
objectB (A a) {
this.a = a;
}
}
@Configuration
class CircularConfig {
@Bean
public objectA a(objectB b) {
return new objectA(b);
}
@Bean
public objectB b(objectA a) {
return new objectB(a);
}
}
public class CircularDepTester {
psvm() {
var annotationConfigApplicationContext =
new AnnotationConfigApplicationContext(
CircularConfig.class
);
}
}
컴포넌트 스캔
@Stereotype
- UML 다이어그램 확장 도구
- 특정 요소를 상황이나 도메인에 알맞게 분류
- Spring이 자동으로 등록된 Bean을 찾도록 해주는 어노테이션
- Spring이 직접 클래스를 검색해서 Bean으로 등록해주는 기능
- Configuration 클래스에 Bean으로 직접 등록하지 않아도 원하는 클래스를 Bean으로 등록 가능
@Stereotype
- 컴포넌트 스캔 어노테이션 (기본형은 모든 Bean을 동일시)
- @Component
- @Repository
- @Controller
- @Service
- @Configuration
@Autowired
생성자 기반 의존관계 주입 선택 권장 이유
→ 그러니까 생성자 주입 방식을 사용하도록 하셈 ㅇㅇ
- 초기화 시 필요한 모든 의존 관계 형성하기 때문에 안전
- 잘못된 패턴 찾을 수 있게 해줌
- 테스트 쉽게 함
- 등록되지 않은 Bean에 의한 프로그램 비정상 종료 방지 가능
- 불변성 확보
- 멀티스레드 환경에서 Thread-Safety 를 보장 가능
- 필드주입
@Autowired
을 쓴 필드는 자동연결 후보가 됨.
- 스프링 IoC 컨테이너에서 빈을 일치시켜 충족할 수 있는 의존성이 가장 많은 생성자가 선택
- 후보 중 어느것도 만족할 수 없는 경우 기본생성자가 선택
Bean Scope
- 6개의 Bean Scope (default: Singleton)
- Singleton : 한 클래스당 Bean은 하나뿐 (Bean 객체 자체가 일치 = 동등성) → 추천
- Prototype
- Request
- Sesssion
- Application
- Websocket
Life cycle
Bean 생성 생명주기 Callback
@PostConstruct
적용된 메소드 호출
- Bean이 InitializingBean 인터페이스 구현 시 AfterPropertiesSet 호출
- @Bean 어노테이션의 initMethod 에 설정한 메소드 호출
Bean 소멸 생명주기 Callback
- @PreDestroy 어노테이션 적용 메소드 호출
- Bean 이 DisposableBean 인터페이스 구현 시 destroy호출
- @Bean 어노테이션의 destroyMethod 에 설정한 메소드 호출
시간순서
- @PostConstruct
- InitializingBean 추상화 메소드
- AppConfig 내 Bean 생성 주기
- AppConfig 내 Bean 소멸 주기
- @PreDestroy
- DisposableBean 추상화 메소드
참고
복수 개의 Bean 설정하기
- 같은 인터페이스
VoucherRepository
를 상속하는 두 클래스 MemoryVoucherRepository
, JdbcVoucherRepository
- Configuration 클래스는 둘에 대한 Bean을 모두 만들었기 때문에
- VoucherRepository 클래스로 Bean을 찾아 IoC 하려는 경우 에러 발생
- 해결책 3가지
- 우선권 있는 클래스에
@Primary
어노테이션 달아주기 → 추천
- 각 클래스에
@Qualifier(”이름”)
어노테이션 달아주기
- 다만, 다른 곳에서 같은 어노테이션으로 명시해서 DI 해줘야 함.
- 아니면 BeanFactoryAnnotationUtils 클래스를 이용해서 qualifier 찾아줘야 함.
Configuration 클래스(파일) 관리
- 한 프로젝트에 여러 Configuration 클래스가 있을 수 있음.
- 이러한 경우 configuration 패키지에 파일들을 몰아넣고,
- 전체 ApplicationConfiguration 파일에 @Component 어노테이션을 이용해서 패키지 자체를 추가하는 방식으로도 사용함.
- 근데,
@SpringBootApplication
어노테이션이 자동으로 컴포넌트 스캔을 해주므로, 그냥 이걸 쓰는게 낫다.