[Spring/Springboot] Bean/싱글톤 패턴/컴포넌트 스캔
2024. 12. 15. 23:06ㆍCS/Spring
스프링 컨테이너 생성 과정
//스프링 컨테이너 생성
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class); //구성 정보를 AppConfig.class로 설정
- 스프링 컨테이너를 생성한다(AppConfig.class) → 스프링 컨테이너 한 스프링 빈 저장소가 있음
- 구성 정보인 AppConfig.class를 활용하여 → 스프링 컨테이너는 파라미터로 넘어온 설정 클래스 정보를 사용하여 스프링 빈 저장소에 스프링 빈을 등록한다.
- 스프링 컨테이너에 빈 의존관계 설정을 준비하고, 설정 정보를 참고하여 의존관계를 주입(DI)한다.
Bean
- Spring 컨테이너가 관리하는 자바의 객체 → Spring은 빈을 통해 객체를 인스턴스화한 후, 객체 간의 의존 관계를 관리함 = 객체가 의존관계를 등록할 때 Spring 컨테이너에서 해당하는 빈을 찾고, 그 빈과 의존성을 만들게 됨
- 빈등록 방법
- @Component → @Autowired : 묵시적 빈 정의
- 클래스에 어노테이션을 추가하고, Autowired로 다른 클래스에서 해당 Bean을 끌어옴
- @Configuration → @Bean : 명시적 빈 정의
- Spring 설정 파일에 Configuration 어노테이션을 추가하고, Bean 어노테이션을 붙여 명시적으로 빈을 지정
- @Component → @Autowired : 묵시적 빈 정의
싱글톤패턴 - @Configuration(명시적 빈 정의)
- 싱글톤패턴
- Spring 컨테이너는 싱글톤 패턴을 적용하지 않아도, 객체 인스턴스를 싱글톤으로 관리함
- 싱글톤 패텅르 위한 지저분한 코드가 들어가지 않아도 됨
- DIP, OCP, test, private 생성자로부터 자유롭게 싱글톤을 사용할 수 있음
- 싱글톤 방식의 주의점 : 여러 클라이언트가 하나의 같은 객체 인스턴스를 공유하기 때문에 Stateless로 설계해야함
- 특정 클라이언트에 의존적이거나, 특정 클라이언트가 값을 변경할 수 있는 필드가 있으면 안됨 → 가급적 읽기만
- 필드 대신에 자바에서 공유되지 않는, 지역변수, 파라미터, ThreadLocal등을 사용해야 함
- Spring 컨테이너는 싱글톤 패턴을 적용하지 않아도, 객체 인스턴스를 싱글톤으로 관리함
- @Configuration
- 스프링 컨테이너는 싱글톤 레지스트리라서 스프링 빈이 싱글톤이 되도록 보장해주어야 하지만, 자바 코드까지 적용하여 보장하기는 어려움 → @Configuration 탄생
- @Configuration을 적용하지 않고, @Bean만 적용하면 어떻게 될까?
- @Bean만 사용해도 스프링 빈으로 등록되지만, 싱글톤을 보장하지 않는다.
- 의존관계 주입이 필요해서 메서드를 직접 호출할 때 싱글톤을 보장하지 않는다.
public class AppConfig{
public MemberService memberService(){
return new MemberServiceImpl(memberRepository());
}
public OrderService orderService(){
return new OrderServiceImpl(memberRepository(), discountPolicy());
}
public MemberRepository memberRepository(){
return new MemoryMemberRepository();
}
...
}
- memberRepository가 3번 호출되고, 각각 다 다른 MemoryMemberRepository 인스턴스를 가지게 됨
- @Configuration을 적용하면?
- @Bean 이 붙은 메서드마다 이미 스프링 빈이 존재하면 존재하는 빈을 반환하고, 스프링 빈이 없으면 셍성해서 스프링 빈으로 등록하고 밚환하는 코드가 동적으로 만들어져 → 싱글톤이 보장됨
- ⇒ 설정정보는 항상 @Configuration 사용할 것
컴포넌트 스캔(@Component) - @Autowired (묵시적 빈 정의)
- 스프링 빈을 등록할 때 설정 정보에 직접 등록할 스프링 빈을 나열하면 → 만약 등록해야할 빈이 수백개가 되면 귀찮고, 설정정보가 커지고, 누락하는 문제 발생⇒ 의존 관계도 자동으로 주입하는 @Autowired 기능 제공
- ⇒ 설정 정보가 없어도 자동으로 스프링이 빈을 등록하는 @ComponentScan 기능 제공
@ComponentScan 과정
- 이전에는 AppConfig에서 @Bean으로 직접 설정 정보를 작성했고, 의존관계를 명시했지만 → 설정 정보 자체가 없기 때문에, 의존관계 주입도 클래스 안에서 해결해야함
- 먼저 컴포넌트 스캔을 사용하면 @ComponentScan을 설정 정보에 붙여줘야함
- 컴포넌트 스캔은 @Compoenent 애노테이션이 붙은 클래스를 스캔해서 스프링 빈으로 등록함
- (cf) @Configuration이 붙은 설정 정보도 자동으로 등록되기 때문에, 중복을 피하려면 어노테이션 제거 필요
- 컴포넌트 스캔은 @Compoenent 애노테이션이 붙은 클래스를 스캔해서 스프링 빈으로 등록함
- 먼저 컴포넌트 스캔을 사용하면 @ComponentScan을 설정 정보에 붙여줘야함
@Componenet
public class MemberServiceImpl implements MemberService{
}
@Componenet
public class OrderServiceImpl implements OrderService{
}
@Componenet
public class MemoryMemberRepository implements MemberRepository{
}
@Componenet
public class RateDiscountPolicy implements DiscountPolicy{
}
- @Autowired의존관계 자동 주입
- 생성자에 @Autowired를 지정하면, 스프링 컨테이너가 자동으로 해당 스프링 빈을 찾아서 주입
@Component
public class MemberServiceImpl implements MemberService{
private final MemberRepository memberRepository;
@Autowired
public MemberServiceImpl(MemberRepository memberRepository){
this.memberRepository = memberRepository;
}
}
- @Autowired를 사용하면, 생성자에서 여러 의존관계도 한번에 주입받을 수 있음 → 생성자에 파라미터가 많아도 다 찾아서 자동으로 주입
@Component
public class OrderServiceImpl implements OrderService{
private final MemberRepository memberRepository;
private final DiscoountPolicy discountPolicy;
@Autowired
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy){
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
}
'CS > Spring' 카테고리의 다른 글
[Spring/Springboot] AOP 관점 지향 프로그래밍 (0) | 2024.12.15 |
---|---|
[Spring/Springboot] API, 프레임워크, 라이브러리의 차이 (0) | 2024.12.15 |
[Spring/Springboot] 제어의 역전 IoC(Inversion of Control) (0) | 2024.12.15 |
[Spring/SpringBoot] 의존 관계 주입 DI(Dependency Injection) (0) | 2024.12.15 |
[Spring/MVC] Controller, Repository, DTO, Domain, Config의 역할 (0) | 2024.08.26 |