제 개인의 공부를 위해 제가 학습한 내용을 토대로 작성된 정보입니다.
잘못된 정보나 부족한 정보가 있을 가능성이 많이 높습니다.
해당 부분 참고하셔서 읽어봐주시고 보충할 부분이 있다면 댓글로 가르침 부탁드립니다.
** 바쁘신 분들은 제일 아래에 정리 블록을 참고해주세요 **
[Spring Container]
ApplicationContext를 스프링 컨테이너 라고 지칭하고, 이는 인터페이스 타입으로 구현되어 있다.
[Spring Container 역할]
내부에 존재하는 애플리케이션 객체(Bean)을 생성, 관리 및 제거 역할을 담당한다. (=생명주기 관리)
@Bean이 적힌 메소드들 (Only 객체를 반환하는 메소드)을 호출하여 반환된 객체를 Spring 컨테이너에 등록
[Spring Container 종류]
<BeanFactory>
1. Spring 컨테이너의 최상위 인터페이스.
2. BeanFactory는 Bean의 생명주기를 관리하는 역할.
3. getBean() 메소드를 통해 인자(argument)에 전달되는 클래스의 Bean을 호출할 수 있다.
4. @Bean이 붙은 메소드의 명을 스프링 Bean으로 사용해 Bean을 등록한다.
<ApplicationContext>
1. BeanFactory의 기능을 상속받아 제공한다.
2. Bean을 관리하고 검색하는 기능을 BeanFactory의 기능으로 제공하고, 그 외에 부가 기능을 제공한다.
3. 부가 기능
A. MessageSource : 메시지 다국화를 위한 인터페이스
B. EnvironmentCapable : 개발, 운영, 환경변수 등으로 나누어 처리하고,
애플리케이션 구동 시 필요한 정보들을 관리하기 위한 인터페이스.
C. ApplicationEventPublisher : 이벤트 관련 기능을 제공하는 인터페이스
[Spring Container 생성]
(1) ApplicationContext applicationContext
= new (2)AnnotationConfigApplicationContext((3)DependencyConfig.class);
(1) Spring 컨테이너을 생성하는 키워드. (인터페이스 타입)
(2) AnnotationConfigApplicationContext는 아래 사진과 같은 과정을 거쳐 BeanDefinition을 생성한다.
(3) DependencyConfig.class 는 Configuration Metadata로써 (@Configuration 애너테이션이 사용된 클래스)
컨테이너가 생성될 때 생성자의 파라미터로 전달되며, Bean을 어떻게 생성할 지에 관한 정보이다.
[BeanDefinition] : 빈 설정 메타정보
Spring은 Bean의 설정 메타 정보를 BeanDefinition 이라는 인터페이스를 통해 관리하고 있다.
Spring 컨테이너는 Bean을 생성할 때 BeanDefinition를 기반으로 Bean을 생성하고
BeanDefinition에 따라서 활용하는 방법이 달라진다.
[BeanDefinition의 속성]
BeanDefinition 속성 명 | BeanDefinition 속성의 역할 |
Bean Class Name | 생성할 Bean의 클래스 명 |
Factory Bean Name | Factory 역할의 Bean을 사용할 경우 이름 (AppConfig) |
Factory Method Name | Bean을 생성할 Factory Method 지정 |
Scope | 싱글톤 (Default) |
lazyInit | Spring 컨테이너를 생성할 때 Bean을 생성하는 것이 아니라, 실제 Bean을 사용할 때 까지 최대한 생성을 지연처리하는지에 대한 여부 |
InitMethodName | Bean을 생성하고 의존관계를 적용한 뒤, 호출되는 초기화 메소드명 |
DestroyMethodName | Bean의 생명주기가 끝나서 제거하기 직전에 호출되는 메소드 명 |
Constructor arguments, Properties | 의존관계 주입에서 사용되는 정보 |
[Spring Bean]
Spring 컨테이너에 사용되는 BeanDefinition (Bean 설정 메타 데이터)에 의해 생성되며 관리되는 객체이다.
[주요 속성]
Class(필수) : Bean으로 등록할 Java 클래스
Id : Bean 고유 식별자
Scope : Spring 컨테이너에 의해 관리될 Bean의 범위.
Constructor ~ arg : 생성 시 생성자에 전달할 파라미터
Property : Bean 생성시 Setter에 전달할 파라미터
[Bean의 생명 주기]
스프링 컨테이너 생성 > 스프링 빈 생성 > 의존관계 주입 > 초기화 콜백 > 사용 > 소멸 전 콜백 > 스프링 종료
[Bean Scope]
Bean이 Spring 컨테이너에서 존재할 수 있는 범위.
Scope Type | Description |
Singleton | 기본값, Spring 컨테이너의 시작과 종료까지 유지되는 범위. |
Prototype | Spring 컨테이너가 Prototype 빈의 생성과 의존관계 주입만 함. |
Request | 웹 요청이 들어오고 나갈 때 까지 유지 |
Session | 웹 세션이 생성되고 종료될 때 까지 유지 |
Application | 웹 서블릿 컨텍스와 같은 범위로 유지 |
Websocket | 단일 BeanDefinition 범위를 WebSocket의 라이블 싸이클까지. Spring ApplicationContext에만 유효하다. |
<싱클톤 스코프 (클래스의 인스턴스가 딱 1개만 생성되는 것을 보장)>
1. Spring 컨테이너의 시작과 함께 생성되어서 Spring 컨테이너가 종료될 때까지 유지.
2. 싱글톤 Bean의 하나의 공유 인스턴스만 관리. (private 생성자를 사용해 외부에서 new를 사용하지 못하도록 막아햐함)
3. 해당 BeanDefinition과 일치하는 ID 또는 ID를 가진 Bean에 대한 모든 요청은 Spring 컨테이너에서 해당 Bean을 반환
4. Spring 컨테이너 종료 시 소멸 메소드도 자동으로 실행.
[싱글톤 패턴의 문제점]
1. 싱글톤 패턴을 구현하는 코드 자체가 많다.
2. 의존관계상 클라이언트가 구체 클래스에 의존한다.
3. 지정해서 가져오기 때문에 테스트가 어렵다.
4. private 생성자를 사용하여 자식 클래스를 만들기 어렵기에 유연성이 떨어진다.
<프로토타입 스코프>
Spring 컨테이너가 생성과 의존관계 주입, 초기화 까지만 관여하는 스코프 이므로,
프로토타입 스코프의 빈은 매번 새로운 빈을 생성해서 반환한다. 즉 사용시점에서는 클라이언트가 모든 책임을 가진다.
<싱글톤 vs 프로토타입 주의>
싱글톤 Bean은 Spring 컨테이너 생성 시점에 같이 생성되고 초기화 되지만,
프로토타입 Bean은 Spring 컨테이너에서 Bean을 조회할 때 생성되고, 초기화 메소드도 실행된다.
[Java 기반 컨테이너 설정]
1. 자바 기반 설정의 가장 중요한 애너테이션
@Configuration - class
@Bean - method
>>메서드가 Spring 컨테이너에서 관리할 새 객체를 인스턴스화, 구성 및 초기화 한다는 것을 나타낸다.
@Bean은 반드시 @Configuration과 함께 사용되어야 한다.
2. 애너테이션을 이용해 Config 클래스 설정하는 방법
Spring 컨테이너(ApplicationContext)의 구현은 아래 애너테이션이 달린 클래스를 파라미터로 전달받는다.
A. @Configuration 클래스
B. @Component 클래스
C. JSR-330 메타데이터
A. @Configuration 클래스가 입력으로 제공될 경우.
@Configuration 클래스 자체, 클래스 내의 모든 @Bean 메소드가 BeanDefinition으로 등록된다.
B @Component 클래스, C JSR-330 클래스가 제공될 경우,
BeanDefinition으로 등록되며,
필요한 경우 해당 클래스 내에서 @Autowired or @Inject 같은 DI 메타데이터가 사용되는 것으로 가정한다.
3. @Bean 애너테이션 사용
@Bean은 메소드 레벨이며, @Configuration-annoted or @Component-annoted 클래스에서 사용 가능.
A.
@Configuration애너테이션 적용된 클래스에서 사용.
B.
@Bean 메소드가 있는 인터페이스를 구현한 구현체에 @Configuration을 사용하여 Bean Configuration 설정
4. @Configuration 애너테이션 사용하기
@Configuration은 해당 클래스가 BeanDefinition(빈 설정 정보)임을 나타내는 애너테이션이다.
@Bean 이 추가된 메소드를 통해 Bean을 선언한다.
@Configuration 클래스의 @Bean 메소드를 호출하여 Bean 사이의 의존성을 정의할 수 있다.
[Bean 의존성]
@Bean 애너테이션이 추가된 메서드는
메서드 Bean을 구축하는데 필요한 의존성을 나타내는 매개 변수를 사용할 수 있다.
[Java 코드에서 애너테이션을 사용해 Spring 컨테이너 구성하는 방법]
@Import 애너테이션 : 다른 Configuration Annoted 클래스의 @BeanDefinition을 가져올 수 있다.
DependencyConfigB 는 @Configuration annoted 클래스인 DependencyConfigA를 @import 함으로써
main 클래스에서 객체화할 때 @DependencyConfigB 만 생성자로 주입받으면, Bean A, B 둘다 사용 가능.
@Import 애너테이션를 통해 많은 @Configuration 클래스들을 기억하지 않아도 코드복잡성을 줄일 수 있다.
================== [Spring 심화 용어 및 애너테이션 정리] ==================
1. <Spring 컨테이너, ApplicationContext>
Spring에서 객체(Bean)을 생성, 수정, 삭제 등 관리하는 존재, 인터페이스로 구현되어 있다.
2. <BeanDefinition>
Spring 컨테이너가 Bean을 생성할 때 전달받는 Bean 설정 정보.Spring컨테이너 구체화하는 코드 중ApplicationContext ac = new AnnotationConfigApplicationContext( ~ );에서 ~ 에 위치하는데 이는 @Configuration annoted 된 객체들이다.
3. <Bean>
Spring 컨테이너가 BeanDefinition를 참고하여 생성하고 관리하는 객체.
4. <BeanFactory>
Spring 컨테이너의 최상위 인터페이스. ApplicationContext에게 Bean을 관리하는 기능을 준다.
5. <@Configuration> : Class Level Annotation.
Spring 컨테이너가 Bean을 생성할 때 필요한 Bean 설정 정보를 담당하는 객체, Class.
@Bean을 사용하는 클래스는 반드시 @Configuration을 작성해야하므로
해당 클래스는 1개 이상의 @Bean을 포함하고 있음을 의미한다.
6. <@Bean> : Method Level Annotation
Only 객체를 반환하는 형태의 메소드에 사용할 수 있으며,
개발자가 작성한 메소드를 통해 반환되는 객체를 Bean으로 만든다.
[Bean ID 설정]
@Bean(name="이름") 을 입력하면 Bean ID 설정, 비어있으면 메소드 이름을 camelCase로 할당
[의존성 주입]
다른 @Bean annoted 메소드를 만들고 반환하는 객체의 생성자()에 주입하고 싶은 객체를 주입한다.
7. <@Component> : Class Level Annotation
개발자가 직접 작성한 Class를 Bean으로 등록하는 기능이며, @ComponentScan의 대상이 된다.
[Bean ID 설정]
@Component(value="이름")을 입력하면 Bean ID설정, 비어있으면 Class 이름을 camelCase로 할당
[의존성 주입]
Component annoted 객체끼리 의존이 있다면 @Autowired로 자동 주입할 수 있다.
@Component를 가진 두 객체가 있을 경우, 다른 객체를 의존하고 있는 객체의 필드변수에 @Autowired 작성.
8. <@ComponentScan> : @Configuration Level Annotation
BeanDefinition없이 자동으로 @Component annoted 객체들을 식별(Scan)하고 Bean으로 등록하는 기능.
@Configuration annoted에 작성해주면 된다.
[식별(Scan) 범위 설정]
basePackages() : Scan을 시작할 패키지를 문자열로 지정.
basePackageClasses() : Scan을 시작할 클래스 타입을 지정.
@Configuration, @Service, @Repository, @Controller 애너테이션 모두 @ComponentScan의 대상이다.
9. <@Import> : Class Level Annotation
기존의 @Configuration annoted 객체의 BeanDefinition을 가져와 (상속받아)
@Import annoted 객체에서 상속받은 객체의 Bean을 모두 사용하기 위한 기능.
<주의사항>
@Import
@Configuration
위의 형태로 함께 사용해야한다.
10. <@BeanScope>
Spring 컨테이너에 Bean이 존재할 수 있는 범위
11. <@Autowired>
@Component로 Bean을 만들때 의존성을 주입해주는 애너테이션. #7 참고
==================== 궁금사항 ==================
@Configuration annoted 객체는 BeanDefinition (AppConfig.class / Dependency.class) 가 되는데
@Configuration은 @Bean 이 1개라도 있는 클래스들에 모두 다 사용하는거로 알고있습니다.
이러면 BeanDefinition이 너무 많아지는게 아닌가요..?
아니면 Spring 컨테이너에 빈이 여러개 존재할 수 있으니
@Configuration이 붙은 클래스당 Bean 을 만드는 것이 당연한 걸까요 ?
제가 BeanDefinition을 잘못 알고있는게 아닌가 걱정이 듭니다.
'백엔드 학습 과정 > Section 2 [재귀함수, 자료구조, 네트워크]' 카테고리의 다른 글
코드스테이츠 백엔드스쿨 42기 Section2 회고록 (0) | 2022.12.17 |
---|---|
#7-2 Spring Framework 심화 [AOP] = 용어, 포인트컷 표현식, AOP 애너테이션 (0) | 2022.12.15 |
#7. Spring Framework [기초] (0) | 2022.12.11 |
Spring IoC / DI 에 관한 학습. // 추가 업뎃 예정 (1) | 2022.12.10 |
#6-3. SQL 자가 학습 확인 문제들 (0) | 2022.12.08 |