스프링 - 기업용 온라인 서비스 기술을 지원
대부분의 스프링 애플리케이션은 웹 애플리케이션이다
웹 = 여러 고객이 동시에 요청 = 고객이 3번 요청하면 객체가 3개 생성되는 것이다 = 요청이 올 때마다 계속 무언가를 만들어야 함
-> 해결 방안 : 싱글톤 패턴 (해당 객체가 딱 1개만 생성되고, 이미 만들어진 객체를 공유해서 효율적으로 사용하도록 설계)
싱글톤 패턴
= 객체 인스턴스가 딱 1개만 생성되는 것을 보장하는 디자인 패턴
= 객체 인스턴스를 2개 이상 생성하지 못하도록 막는다
public class SingletonService {
private static final SingletonService instance = new SingletonService();
public static SingletonService getInstance() {
return instance;
}
private SingletonService() {
}
public void logic() {
System.out.println("싱글톤 객체 로직 호출");
}
}
private를 사용해 생성자를 막아서 외부에서 new로 객체 인스턴스가 생성되는 것을 막아야 한다 !!
<싱글톤 패턴 문제점>
- 코드가 길다
- DIP 위반 ( 클라이언트가 구체 클래스에 의존하기 때문)
- OCP 위반할 가능성이 높다 ( 클라이언트가 구체 클래스에 의존해서)
...
-> 스프링 컨테이너는 이 문제점들을 모두 해결해면서 객체 인스턴스를 싱글톤으로 관리한다
싱클톤 레지스트 : 싱글톤 객체를 생성하고 관리하는 스프링 컨테이너의 기능
스프링은 99% 기본적으로는 싱글톤 방식으로 동작한다!
<싱글톤 방식의 주의점>
싱글톤 객체는 상태를 유지하게 설계하면 안된다! (무상태로 설계해야함)
- 특정 클라이언트에 의존적인 필드가있으면 안됨
공유되는 필드(StatefulService의 price)의 값을 특정 클라이언트가 변경한다.
=> 스프링 빈은 항상 무상태stateless로 설계하자 !!
AppConfig에 호출 로그 남김
-> 스프링 컨테이너가 각각 @Bean을 호출해서 스프링 빈을 생성하기 때문에 memberRepository()는 3번 호출되어야 하지 않나 ?
-> 하지만 출력 결과는 1번만 호출됨
= 스프링 컨테이너가 어떻게든 싱글톤을 보장한다는 것을 알 수 있음
-------->
<@Configuration과 바이트코드 조작의 마법>
스프링이 AppConfig가 아니라 AppConfig@CGLIB클래스를 스프링 빈으로 등록한 것 !
이 임의의 다른 클래스가 바로 싱글톤이 보장되도록 해준다.
AppConfig@CGLIB 예상 코드
@Bean
public MemberRepository memberRepository() {
if (memoryMemberRepository가 이미 스프링 컨테이너에 등록되어 있으면?) { return 스프링 컨테이너에서 찾아서 반환;
} else { //스프링 컨테이너에 없으면
기존 로직을 호출해서 MemoryMemberRepository를 생성하고 스프링 컨테이너에 등록 return 반환
} }
@Bean만 사용하면 스프링 빈으로는 등록되지만, 싱글톤은 보장하지 않는다.
따라서 스프링 설정 정보는 항상 @Configuration을 사용해야한다.
<컴포넌트 스캔>
등록해야 할 스프링 빈이 엄청 많이 생기면 문제 발생
-> 스프링은 자동으로 스프링 빈을 등록하는 컴포넌트 스캔이라는 기능을 제공
@ComponentScan을 설정 정보에 붙여주면 된다
@ComponentScan을 쓰면 @Autowired(의존관계를 자동으로 주입해줌)도 사용하게 된다.
@ComponentScan 은 @Component 가 붙은 모든 클래스를 스프링 빈으로 등록한다.
이때 스프링 빈의 기본 이름은 클래스명을 사용하되 맨 앞글자만 소문자를 사용
Ex> MemeberServiceImple -> memberServiceImpl
생성자에 @Autowired 를 지정하면, 스프링 컨테이너가 자동으로 해당 스프링 빈( 타입이 같은 빈을 찾아서 )을 찾아서 주입
<탐색 위치와 기본 스캔 대상>
basePackages = "hello.core" 로 탐색 위치를 지정한다
지정하지 않으면 @ComponentScan이 붙은 설정 정보 클래스의 패키지부터 시작된다
-> 설정 정보 클래스의 위치를 프로젝트 최상단에 두는게 가장 좋은 방법이다!!
<컴포넌트 스캔 기본 대상>
@Component, @Controller, @Service, @Repostiroy, @Configuration
애노테이션이 특정 애노테이션을 들고 있는 것을 인식할 수 있는 것은 자바 언어가 지원하는 기능이 아닌 스프링이 지원하는 기능
<스프링의 부가 기능>
@Controller : 스프링 MVC 컨트롤러로 인식
@Repository : 스프링 데이터 접근 계층으로 인식하고, 데이터 계층의 예외를 스프링 예외로 변환해준다.
@Configuration : 앞서 보았듯이 스프링 설정 정보로 인식하고, 스프링 빈이 싱글톤을 유지하도록 추가 처리를 한다.
@Service : 특별한 처리를 하지 않는다.
<필터>
includeFilters : 컴포넌트 스캔 대상을 추가로 지정한다.
excludefilters : 컴포넌트 스캔에서 제외할 대상을 지정한다.
FilterType은 5가지 옵션이 있다. (ANNOTATION, ASSIGNABLE_TYPE, ASPECTJ, REGEX, CUSTOM)
<중복 등록과 충돌>
자동 빈 등록 vs 자동 빈 등록 -> ConfilictingBeanDefinitionException 예외 발생
수동 빈 등록 vs 자동 빈 등록 -> 수동 빈 등록이 우선권을 가진다. (수동 빈이 자동 빈을 오버라이딩)
'spring' 카테고리의 다른 글
스프링 스터디_마지막 (0) | 2022.02.24 |
---|---|
스프링 스터디 6주차 (0) | 2022.02.17 |
스프링 스터디 4주차 (0) | 2022.02.03 |
스프링 스터디 3주차 (0) | 2022.01.27 |
스프링 2주차 스터디 (0) | 2022.01.20 |