본문 바로가기
Spring

Spring Framework 3

by irerin07 2019. 12. 5.
728x90

Component, ComponentScan
@ComponentScan을 붙이고 있는 configuration부터 스캔을 시작한다. @SpringBootApplication은 내부적으로 @ComponentScan을 가지고 있다.
basePackageClasses를 사용하면 해당 어플리케이션이 담겨있는 패키지와 해당 패키지의 하위 패키지 전부를 스캔한다.
하지만 해당 패키지 외부에 있는 것들은 스캔하지 않는다.
@Filter ->  컴포넌트 스캔을 한다고 해서 모든 Annotation들을 스캔해서 Bean으로 등록하는 것이 아니다. Filter를 통해서 걸러내는 것들도 있다.
ComponentScan의 중요 설정
- 어디부터 어디까지 스캔을 할 것인가 -> basePackageClasses
- 어떤것들은 걸러낼것인가 -> Filter

기본적으로 @Component를 들고 있는 것들이 Bean으로 등록 된다.
단점
- 싱글톤 scope의 Bean들은 초기에 생성을 하게 되기 때문에 등록해야 하는 Bean이 많은 경우 초기 구동 시간이 오래 걸릴 수 있다.

스프링5 부터 펑션을 사용해 빈 등록을 할 수 있게 되었다 -> 구동 시간에 좀 더 좋은 효율을 보인다(reflection 혹은 proxy 같은 것들을 사용하지 않는다), 좀 더 조작을 할 수 있다.

동작 원리
BeanFactoryPostProcessor를 구현한 ConfigurationClassPostProcessor와 연결이 되어있다. 실제 스캐닝은 ConfigurationClassPostProcessor에 의해 이루어진다.

---------------------

Bean의 Scope
스프링은 설정을 따로 해주지 않으면 기본적으로 Singleton으로 Bean을 생성한다.
Singleton Scope? -> Application 전반에 걸쳐 해당 Bean의 instance가 오직 하나라는 것
Prototype Scope? -> 매번 새로운 Bean의 instance를 생성한다.
Bean의 Scope를 손쉽게 관리 할 수 있는것이 Spring의 장점이다

Prototype의 Bean이 Singleton Bean을 참조하면?
- 별 문제 없다.
- Singleton으로 생성된 Bean은 어차피 단 하나밖에 없으므로 매번 같은 instance가 들어온다.
- Prototype으로 생성된 Bean은 매번 새롭지만 해당 Bean이 참조하는 Singleton Bean은 항상 똑같다. 

Singleton의 Bean이 Prototype Bean을 참조하면?
- 조금 복잡해진다.
- Singleton으로 생성된 Bean은 이미 하나로 고정되기 때문에 참조하는 Prototype Bean의 property 역시 고정되버린다. -> 즉 매번 같은 Prototype의 Bean을 참조한다.
- 의도대로 작동하지 않는다.
-- proxyMode를 설정해 해결
--- proxyMode = ScopedProxyMode.TARGET_CLASS
--- 해당 Bean을 클래스 기반의 프록시로 감싸라는 뜻 -> 다른 Bean들이 이 Bean을 사용할 때 해당 Proxy Bean을 사용하게 해라 라고 설정하는 것이다.
--- 다른 instance들이 Prototype Scope의 Bean을 직접 참조하면 안되고 Proxy를 거쳐야한다.
---- 왜 직접 참조하면 안되는가? -> 다른 instance들이 Prototype Bean을 직접 참조하면 매번 새로 바꿔줄 수가 없다.
---- CG LIB을 사용한다.
--- 실제 instance를 감싸는 Proxy instance가 만들어지고 그 Proxy instance가 Bean으로 등록이 된다. -> 그리고 해당 Proxy Bean을 주입을 하게 된다.
--- Proxy역시 Prototype을 상속해서 만들었기 때문에 Type이 같다. -> 주입이 가능해진다.

-- 혹은 ObjectProvider를 사용

Singleton 객체 사용시 주의할 점
- Thread-Safe한 방법으로 코딩을 해야한다. -> 단 하나밖에 없기 때문에 Thread-Safe하지 않다면 문제가 생길 수 있다.
- 모든 Singleton Scope의 Bean들은 ApplicationContext를 만들때 생성된다.


-------------------

Environment 

ApplicationContext는 여러가지 기능을 가지고 있다.
그 중 하나인 EnvironmentCapable
Profile - Bean들의 묶음 -> 각각의 환경에 따라 혹은 특정 환경에서만 어떠한 Bean들을 등록해야 하는 경우에 사용하는 기능
Environment의 역할은 활성화할 Profile 확인 및 설정

클래스 혹은 메소드에 @Profile("profile 이름")을 사용해서 적용할 수 있다.
테스트 환경에서는 A라는 Bean을, 배포 환경에서는 B라는 Bean을 사용할 수 있게 된다.

Profile 표현식에는 !, &, | 이 세가지를 사용할 수 있다.

Property
Application에 등록된 여러가지 Key, value쌍으로 제공되는 Property에 계층형으로 접근할 수 있는 기능
계층형 접근 - Property에는 우선순위가 있다.
-- ServletConfig 매개변수
-- ServletContext 매개변수
-- JNDI
-- JVM 시스템 프로퍼티(-Dkey="value")
-- JVM 시스템 환경 변수(운영체제 환경 변수)

MessageSource
국제화(i18n)기능을 제공하는 인터페이스 - 메세지를 다국화 하는 방법
getMessage - messages.properties를 사용하여 Locale에 따른 메세지를 출력할 수 있다.
Reloading 기능이 있는 메세지 소스도 사용할 수 있다.


ApplicationEventPublisher
이벤트 기반의 프로그래밍을 할 때 유용한 interface
스프링 4.2 이전에는 이벤트 클래스에선 항상 ApplicationEvent를 상속 받았어야 했다.
이벤트를 핸들링 하기 위해서는 EventHandler를 Bean으로 등록해야한다.
스프링 4.2 이전에는 ApplicationEventListener를 상속 받았어야 했다.
EventHandler 내부에서 전달받은 이벤트로 여러 작업을 할 수 있다.
스프링 4.2 이후부터는 Event는 Bean으로 등록 할 필요가 없어지고 이벤트를 처리하는 메소드 위에 @EventListener를 적용하면 된다.
기본적으로 순차적으로 실행이 된다. -> A스레드에서 A 이벤트를 실행하고 B 스레드에서 B 이벤트를 실행하는 것이 아니라 A이벤트 다음에 B 이벤트가 실행된다...기본적으로 syncronized
순서를 정하고 싶다면 이벤트를 처리하는 메소드 위에 @Order를 사용한다.
비동기적으로 실행하고자 한다면 Async를 사용한다. -> 순서는 보장이 안된다.
비동기적으로 실행한다면 각각의 thread pool에서 따로 돌게 되고 thread schedueling에 따라 달라지기에 Order가 의미가 없어진다.

728x90

'Spring' 카테고리의 다른 글

토비의 스프링 1일  (0) 2023.07.14
Spring Framework 4  (0) 2019.12.12
Spring Framework 2  (0) 2019.12.04
Spring Framework 1  (0) 2019.12.04
1  (0) 2019.08.25