spring

스프링 스터디 5주차

조쿼카 2022. 2. 10. 22:37

스프링 - 기업용 온라인 서비스 기술을 지원

대부분의 스프링 애플리케이션은 웹 애플리케이션이다

웹 = 여러 고객이 동시에 요청 = 고객이 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 위반할 가능성이 높다 ( 클라이언트가 구체 클래스에 의존해서)

...

 

-> 스프링 컨테이너는 이 문제점들을 모두 해결해면서 객체 인스턴스를 싱글톤으로 관리한다

싱클톤 레지스트 : 싱글톤 객체를 생성하고 관리하는 스프링 컨테이너의 기능

 

 

동일한 객체 공유&nbsp;

 

스프링은 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