- Bean : 스프링 컨테이너에 의해 인스턴스화되고, 조립되고, 관리되는 객체
- Spring Bean : 스프링 컨테이너에 등록된 객체. 주로 @Bean, @Component, @Service 같은 어노테이션을 붙여 특정 객체를 빈으로 등록한다.
스프링 컨테이너 생성 → Bean의 생성 → 의존성 주입 → 초기화 콜백 → Bean의 사용 → 소멸 전 콜백 → 스프링 종료
초기화 콜백 : 애플리케이션 서버가 시작될때 DB 와 연결설정하는 등 외부 자원과의 연결을 설정
소멸 전 콜백 : 서버 종료 시 DB연결 미리 끊는 종료 작업
-
- 인터페이스 (InitializaingBean, DisposableBean 이용)
public class ExampleBean implements InitializingBean, DisposableBean { @Override public void afterPropertiesSet() throws Exception { // 초기화 콜백 } @Override public void destroy() throws Exception { // 소멸 전 콜백 } }
- 설정 정보에 초기화 메소드, 종료 메소드 지정
-
public class ExampleBean { public void initialize() throws Exception { // 초기화 콜백 (의존관계 주입이 끝나면 호출) } public void close() throws Exception { // 소멸 전 콜백 (메모리 반납, 연결 종료와 같은 과정) } } @Configurationclass LifeCycleConfig { @Bean(initMethod = "initialize", destroyMethod = "close") public ExampleBean exampleBean() { // 생략 } }
- @PostConstruct, @PreDestroy 어노테이션 사용 → 가장 권장되는 방법 !
-
public class ExampleBean { //초기화 콜백 @PostConstruct public void initialize() throws Exception {} //소멸 전 콜백 @PreDestroy public void close() throws Exception {} }
1. 어노테이션이란?
- 프로그램에게 추가적인 정보를 제공해주는 메타데이터 (데이터를 위한 데이터)
2. 용도
- 컴파일러에게 코드 작성 문법 에러를 체크하도록 정보 제공
- 소프트웨어 개발 툴이 빌드나 배치 시 코드를 자동으로 생성할 수 있도록 정보 제공
- 실행 시 (런타임) 특정 기능을 실행하도록 정보 제공
3. 어노테이션 종류
- JDK 표준 어노테이션ex) @Override, @Deprecated, @SuppressWarnings
- : 자바에서 기본적으로 제공하는 어노테이션
- meta 어노테이션
- @Retention : 어노테이션의 정보를 어느 범위까지 유지할 지 결정
- RetentionPolicy.SOURCE : 컴파일 전까지만 유효하며 컴파일 이후에는 사라짐
- RetentionPolicy.CLASS : 컴파일러가 클래스를 참조할 때까지 유효
- RetentionPolicy.RUNTIME : 컴파일 이후에도 JVM에 의해 계속 참조 가능. 즉, Java로 작성한 코드가 돌아가는 동안에 계속 유지된다
- @Target : 생성할 어노테이션이 적용될 수 있는 위치를 나열
- ElementType.TYPE : 클래스, 인터페이스, enum에만 어노테이션 사용가
- ElementType.METHOD : 메소드 선언시 어노테이션 사용 가능
- @Documented : 어노테이션 정보가 javadoc 문서에 포함되도록 한다
- @Inherited : 하위 클래스가 어노테이션을 상속받을 수 있도록 한다
- @Repeatable : 반복적으로 어노테이션을 선언할 수 있다
- @Retention : 어노테이션의 정보를 어느 범위까지 유지할 지 결정
- : 어노테이션을 정의할 때 사용되는 어노테이션으로, 어노테이션을 위한 어노테이션이다
- 커스텀 어노테이션
@Target({ElementType.[적용대상]}) @Retention(RetentionPolicy.[정보유지 범위]) public @interface [어노테이션명]{ public 타입 elementName() [default 값] ... }
- : 사용자가 메타 어노테이션을 이용하여 직접 구현한 어노테이션
1. 빈을 수동으로 등록 - @Bean 과 @Configuration 이용하기
@Configuration
public class ResourceConfig {
@Bean
public myBean myBean() {
return new myBean();
}
}
설정 클래스 파일에 @Configuration 어노테이션을 적용해주고, 그 안에서 스프링 빈으로 등록하고싶은 메소드에 대해 @Bean 어노테이션을 적용시켜주면 스프링 컨테이너에 빈이 등록된다.
- 과정 : 스프링 컨테이너는 @Configuration이 붙어있는 클래스를 자동으로 빈으로 등록해주고, 해당 클래스를 파싱해서 @Bean이 있는 메소드를 찾아 빈을 생성한다.
- @Bean을 사용하는 클래스에는 반드시 @Configuration 어노테이션을 활용해서 해당 클래스에서 빈을 등록하겠다고 명시해주어야 한다.→ 싱글톤이란? : 어떠한 객체를 단 한 번만 생성하고, 생성된 객체를 어디서든지 참조할 수 있도록 하는 패턴
- → @Bean 객체가 싱글톤으로 등록됨을 보장받기 위해
2. Bean을 자동으로 등록 - @Component 이용하기 → 권장!
스프링은 Component Scan을 사용해 @Component 어노테이션이 있는 클래스들을 찾아 자동으로 빈으로 등록해준다.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
@AliasFor(annotation = Component.class)
String value() default "";
boolean proxyBeanMethods() default true;
}
@Configuration의 하위 어노테이션으로 @Configuration, @Repository, @Service, @Controller, @RestController 등이 있다.
- @Bean은 메소드에 적용시키고, 개발자가 직접 변경하기 어려운 대상(외부 라이브러리)에 사용하는 것이 권장됨
- @Component는 클래스에 사용하고, 개발자가 직접 변경이 가능한 대상에 사용
@ComponentScan이란?
@ComponentScan 어노테이션이 작성된 패키지 이하의 모든 클래스들을 순회하여 @Component 어노테이션이 붙은 클래스들을 스캔하여 빈을 찾아 Spring Container에 등록한다. 스프링부트에서는 @SpringBootApplication이 @ComponentScan을 들고있다.
스프링부트는 @SpringBootApplication 어노테이션이 선언된 클래스의 패키지 및 그 하위 패키지만 스캔하기 때문에 내가 생성하는 클래스들을 @SpringBootApplication 어노테이션이 선언된 클래스가 속한 패키지 내에 있도록 해주어야 한다.
위 사진과 같으면 클래스들이 @Application이 속한 com.ceos20.spring_boot 패키지 내에 있지 않아 내가 생성한 클래스들을 스캔하지 못하여 오류 생긴다.
따라서 com.ceos20.spring_boot 패키지 내에 클래스들이 위치하도록 해주어야 한다.
@ComponentScan 옵션
- @ComponentScan의 탐색 범위를 직접 지정할 수 있다.
@ComponentScan(basePackage = "경로")
basePackage : 탐색할 패키지의 시작위치. 하지만 default 방식(@SpringBootApplication이 존재하는 패키지)을 권장한다.
- includeFilters & excludeFilters
- includeFilters : ConponentScan의 대상이 아니지만, ComponentScan에 포함시켜야 하는 경우에 사용
@ComponentScan(
includeFilters = {
@Filter(type = FilterType.상수, classes = 클래스명.class) })
- excludeFilters : ConponentScan의 대상이지만, ComponentScan에서 제외시켜야 하는 경우에 사용
```
@ComponentScan(
excludeFilters = {
@Filter(type = FilterType.상수, classes = 클래스명.class) })
```
FilterType종류
- ANNOTATION : 주어진 어노테이션이 명시된 컴포넌트를 필터
- ASSIGNABLE_TYPE : 주어진 타입을 필터
- ASPECTJ : AspectJ 패턴을 사용하여 필터
- REGEX : 정규식을 이용한 필터
- CUSTOM : 직접 만든 필터를 이용한 필터@ComponentScan(excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Ignore.class))
- ex) Ignore라는 어노테이션이 붙인 빈들은 스캔에 포함시키지 않으려면 아래와 같이 필터링 할 수 있다.
@ComponentScan 동작과정
ClassPathBeanDefinitionScanner : 클래스 경로 내의 컴포넌트를 스캔하고 이를 Bean Definition객체로 변환하는 기능을 수행한다.
- @ComponentScan 어노테이션에 지정된 basePackages 속성을 통해 어떤 패키지 하위에서 빈을 스캔할지 확인
- base-package 하위의 모든 클래스들을 로딩하여 빈 후보인지 확인
- 빈 후보라면 Bean Definition(스프링 컨테이너가 해당 빈을 생성하고 관리하는데 필요한 모든 정보) 을 생성
- 이 정를 토대로 빈을 생성하게 된다.
'백 > spring boot' 카테고리의 다른 글
Base Entity 구현 (0) | 2024.09.29 |
---|---|
JPA 관련 문제들 (주로 N+1문제) (0) | 2024.09.29 |
IoC/DI, AOP, PSA (0) | 2024.09.29 |
Spring Security2 - 로그아웃 (0) | 2024.08.16 |
spring security2 - refresh토큰 서버측 저장 (0) | 2024.08.16 |