2022. 9. 25. 13:25ㆍ자바 & Spring
스프링 컨테이너
스프링 컨테이너를 이용해 객체를 스프링 빈으로 등록하고 컨테이너에서 스프링 빈을 찾아 사용할 수 있다.
스프링 컨테이너는 다음과 같은 이점을 제공해줌으로써 개발자가 객체 지향적인 개발을 할 수 있게 도와준다.
의존관계 주입 (DI)
- 컨테이너가 의존관계를 자동으로 주입
제어의 역전 (IoC)
- 객체는 자신의 로직만 실행하고 프로그램의 제어흐름을 외부(스프링 컨테이너) 에서 실행.
싱글톤 패턴
- 객체를 빈으로 등록해 찾아 사용할 수 있어 싱글톤 패턴을 보장해준다.
스프링 컨테이너를 만드는 방법
1) XML 기반으로 생성
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="memberService" class="studyhello.projectbuildname.member.MemberServiceImpl">
<constructor-arg name="memberRepository" ref="memberRepository" />
</bean>
<bean id="memberRepository" class="studyhello.projectbuildname.member.MemoryMemberRepository" />
<bean id="orderService" class="studyhello.projectbuildname.order.OrderServiceImpl">
<constructor-arg name="memberRepository" ref="memberRepository" />
<constructor-arg name="discountPolicy" ref="discountPolicy" />
</bean>
<bean id="discountPolicy" class="studyhello.projectbuildname.discount.RateDiscountPolicy" />
</beans>
XML 파일에 beans 태그로 설정, bean 태그를 이용해 스프링 빈을 등록할 수 있다.
bean 태그의 속성값인 id로 빈 이름, class 로 구현 클래스를 지정해줄 수 있다.
이는 @Configuration 으로 설정 파일을 만드는 것과 큰 차이가 없다.
2) 어노테이션 기반의 자바 설정 클래스
@Configuration 을 붙인 AppConfig 클래스
ApplicationContext 의 구현체가AppConfig 클래스를 설정 정보로 활용한다.
스프링 컨테이너를 보통 ApplicationContext, BeanFactory 로 구분하곤 하는데 주로 ApplicationContext를 사용한다.
AppConfig 클래스를 구성 정보로 지정해 스프링은 이를 바탕으로 컨테이너를 생성한다.
위처럼 스프링 빈을 등록할 때 자바 코드의 @Bean, 아니면 XML의 bean 태그를 통해 등록할 스프링 빈을 우리가 지정해주었다.
하지만 빈의 개수가 많아진다면, 이렇게 설정 정보에 일일이 등록하기는 귀찮을 것이다.
컴포넌트 스캔(Component Scan)
- 스프링이 설정 정보가 없어도 자동으로 스프링 빈을 등록해주는 기능이다.
- 의존관계를 자동으로 대입해주는 @Autowired도 제공.
- AppConfig 클래스에서 @Bean으로 빈으로 등록할 모든 클래스를 나열해줄 필요 없이, 빈으로 등록할 클래스에 @Component 를 붙여주면 됨.
- @Component 가 아니더라도 이를 포함하는 어노테이션이 있다면 성립.
컴포넌트 스캔 추가 대상
- @Controller
- @Repository
- @Service
- @Configuration
해당 어노테이션 모두 @Component 를 포함하고 있다.
@Configuration
@ComponentScan(
excludeFilters = @Filter(type = FilterType.ANNOTATION,
classes = Configuration.class))
public class AppConfig {
}
- @Component 가 붙은 클래스를 스캔해 스프링 빈으로 등록.
@Component 특성
- @Component 가 붙은 클래스를 스캔, 스프링 빈으로 등록.
- 빈 이름은 기본적으로 클래스명을 사용. 앞 글자는 소문자이다.
- @Component 속성으로 빈 이름을 직접 지정해줄 수 있다.
- 컴포넌트 스캔을 할 때 하위 패키지들 모두가 자동으로 컴포넌트 스캔의 대상이 된다.
클라이언트에서 설정 정보로 AppConfig를 넘겨주고, ApplicationContext의 구현체인 AnnotationConfigApplicationContext에서 ac.getBean()으로 스프링 빈을 불러오는 것은 동일하다.
public class MemberApp {
public static void main(String[] args) {
ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
MemberService memberService = ac.getBean("memberService", MemberService.class);
}
}
필터 (@Filter)
@ComponentScan 의 속성으로 @Filter 를 추가해 컴포넌트 스캔 대상을 직접 추가하거나, 제외할 수 있다.
includeFilters : 컴포넌트 스캔 대상을 추가로 지정.
excludeFilters : 컴포턴트 스캔에서 제외할 대상을 지정.
@IncludeComponent
public class A {
}
@ExcludeComponent
public class B {
}
다음과 같이 어노테이션을 통해 컴포넌트 스캔 대상을 추가 지정, 제외할 수 있음
A 클래스를 스캔 대상에 추가, B 클래스를 제외
@Configuration
@ComponentScan(
includeFilters = @Filter(type = FilterType.ANNOTATION, classes = IncludeComponent.class),
excludeFilters = @Filter(type = FilterType.ANNOTATION, classes = ExcludeComponent.class)
)
static class AppConfig {
}
의존관계 자동 주입
스프링컨테이너는 우리가 지정한 클래스의 객체에 의존관계를 자동으로 주입해준다.
의존관계 주입의 종류로는 3가지가 있다.
- 생성자 주입
- Setter 주입
- Field 주입.
그 중에서 생성자 주입을 사용하는 것이 좋다. 최근 DI는 대부분 생성자 주입을 사용하는 추세이다.
why?
- 대부분의 의존관계 주입은 한번 일어나면 어플리케이션이 종료될 때까지 변경할 일이 거의 없음. (불변 객체)
- 수정자 주입을 사용하면 setter 함수를 만들어야 하는데, 이를 통해 외부에서 변경할 수 있기에 위험!
- 생성자 주입은 객체를 생성할 때 딱 한번만 호출되므로 불변하게 설계할 수 있다.
- 의존관계 누락을 방지할 수 있음.
생성자 주입을 사용하면 필드에 final을 붙여 Null Point Exception도 컴파일 시점에서 막아준다. 이처럼 값이 설정되지 않는 문제도 해결할 수 있음.
Autowired 를 통한 생성자 주입
- @Autowired는 의존관계를 자동으로 주입해준다. 의존 관계를 직접 명시해줄 필요 X
- 컨테이너에서 자동으로 해당 스프링 빈을 찾아 주입한다.
- 타입이 같은 빈을 찾아서 주입
@RequiredArgsConstructor
롬복 라이브러리가 제공하는 기능으로 final 이 붙은 필드나 @NotNull 이 붙은 필드를 모아 생성자를 자동으로 만들어준다.
이는 @Autowired가 붙은 생성자를 만들지 않고도 간단하게 의존성을 주입해줌.(final, @NotNull 이 붙은 필드만!)
@RestController :
컴포넌트 스캔 - 스프링 빈으로 등록되게 함.
@RequiredArgsConstructor :
final 키워드가 붙은 commentService, userService,
boardService에 자동으로 의존관계를 주입해준다.
flow
- 어플리케이션 실행.
- 컴포넌트 스캔의 대상이 되어 BoardController가 스프링 빈으로 등록됨. BoardController 는 스프링 빈으로 등록되었기 때문에 싱글톤을 보장한다. (하나의 객체만 반환.)
- final 키워드가 붙은 필드 3개는 컨테이너가 의존성을 자동 주입, 어플리케이션이 끝날 때까지 불변한다.
의존관계 주입을 사용할 때는 어플리케이션 시작 ~ 종료 시점까지 불변하게 설계하는 것이 중요!
BoardController 의 세 필드 UserService, BoardService, CommentService 에는 @Service 가 붙는다.
@Service -> @Component 를 포함해 컴포넌트 스캔 대상이 된다.
Controller, Service, Repository 세 계층으로 분리해서 사용하더라도 스프링 컨테이너가 객체를 알아서 관리.
빈으로 등록해 자동으로 의존성을 주입해주고, 컴포넌트 스캔을 통해 빈으로 등록, 싱글톤을 보장해준다.
따라서 개발하기 매우 편리하다.
'자바 & Spring' 카테고리의 다른 글
JDBC(Java Database Connectivity) (0) | 2022.11.02 |
---|---|
빈 생명주기 콜백 (0) | 2022.10.26 |
싱글톤(singleton) 패턴 (0) | 2022.09.24 |
Spring 특징과 장점 (0) | 2022.09.17 |
JUnit 단위 테스트 (0) | 2022.09.07 |