1. XML 설정 사용
- XML을 사용하면 컴파일 없이 빈 설정 정보를 변경할 수 있다.
- 빈 설정에 에러가 났을 경우 컴파일러가 이를 잡아주지 못하고 문제가 생겼을 경우에 원인을 찾는게 어렵다.
- 최근에는 스프링 부트를 많이 사용하면서 XML기반의 설정은 잘 사용하지 않는다.
XML 설정 방법
- resources폴더 아래에 xml파일을 생성하여 설정한다.
[appConfig.xml]
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="memberService" class="spring.example.member.MemberServiceImpl" scope="singleton">
<constructor-arg name="memberRepository" ref="memberRepository"/>
</bean>
<bean id="memberRepository" class="spring.example.member.MemoryMemberRepository"/>
<bean id="orderService" class="spring.example.order.OrderServiceImpl">
<constructor-arg name="memberRepository" ref="memberRepository"/>
<constructor-arg name="discountPolicy" ref="discountPolicy"/>
</bean>
<bean id="discountPolicy" class="spring.example.discount.RateDiscountPolicy"/>
</beans>
id : 등록할 빈의 이름
class : 패키지명을 포함한 빈으로 정의할 클래스
scope : 빈의 스코프(singleton, prototype, reqeust...), 설정하지 않으면 기본적으로singleton이 적용된다.
autowired : 기본적으로 타입과 이름, 생성자등이 있다.(autowired방법)constructor-arg : 생성자 주입을 할 경우 사용한다. 생성자의 매개변수를 등록해야한다.
constructor-arg를 사용하는 빈들은 아래와 같이 생성자 주입이 들어있다.
//[MemberServiceImpl]
public class MemberServiceImpl implements MemberService{
private final MemberRepository memberRepository;
public MemberServiceImpl(MemberRepository memberRepository){
this.memberRepository = memberRepository;
}
...
}
//[OrderServiceImpl]
public class OrderServiceImpl implements OrderService{
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy){
this. memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
...
}
XML 설정 테스트
public class XmlAppContext {
@Test
void xmlAppContext(){
ApplicationContext ac = new GenericXmlApplicationContext("appConfig.xml");
MemberService memberService = ac.getBean("memberService", MemberService.class);
assertThat(memberService).isInstanceOf(MemberService.class);
}
}
[결과]
Singleton Bean으로 생성된걸 볼 수 있다.
21:27:56.135 [Test worker] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 4 bean definitions from class path resource [appConfig.xml]
21:27:56.139 [Test worker] DEBUG org.springframework.context.support.GenericXmlApplicationContext - Refreshing org.springframework.context.support.GenericXmlApplicationContext@3cf16a77
21:27:56.187 [Test worker] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'memberService'
21:27:56.206 [Test worker] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'memberRepository'
21:27:56.215 [Test worker] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'orderService'
21:27:56.216 [Test worker] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'discountPolicy'
2. XML 컴포넌트 스캔
- 위 방법과 같이 으로 빈을 하나하나 등록하면 너무 번거롭기 때문에... 컴포넌트 스캔을 사용해서 지정한 패키지 내에 있는 컴포넌트를 간단하게 모두 가져오는 방법이 있다.
[appConfig.xml]
<context:component-scan base-package="spring.example"/>
base-package 기준으로 @Component
애노테이션을 붙인 클래스들을 스캔하여 빈으로 등록해준다.
Component 어노테이션 외에도@Service
,@Controller
,@Repository
,@Configuration
애노테이션이 붙은 클래스들도 스캔을하는데 그 이유는 해당 어노테이션에 Component애노테이션이 포함되어 있기 때문이다.
Component 관련 애노테이션은 클래스 위에 해당 애노테이션을 붙이면 된다.
base-package에 ','를 사용하여 여러개의 패키지를 쓸 수 있다.
<context:component-scan base-package="spring.example.member , spring.example.order"/>
3. JAVA 설정 파일 사용
- String 프레임워크는 3.1부터 Java 기반의 설정을 지원하기 시작했다.
- XML문서는 길어지면 가독성이 떨어지고 String형 문서이기때문에 오타를 확인하거나 디버깅하기가 어렵다.
- Java 설정 방식은 컴파일러의 도움을 받기 때문에 설정 정보 오류를 미리 알 수 있다.
- 1번에서 작성한 xml config파일을 java설정으로 바꿀 수 있다.
@Configuration
public class AppConfig {
@Bean
public MemberService memberService(){
return new MemberServiceImpl(memberRepository());
}
@Bean
public MemberRepository memberRepository(){
return new MemoryMemberRepository();
}
@Bean
public OrderService orderService(){
return new OrderServiceImpl(memberRepository(), discountPolicy());
}
@Bean
public DiscountPolicy discountPolicy(){
return new RateDiscountPolicy();
}
}
컴포넌트 안에 작성된 @Bean을 등록시켜 준다.
4. @SpringBootApplication
Spring boot를 사용하면 최상단에 @SpringBootApplication이 붙은 클래스가 하나 생성된다.
@SpringBootApplication은 @Configuration과 @ComponentScan을 가지고 있기 때문에 개발자가 특별한 선언을 하지 않아도 해당 클래스의 하위 패키지에 Component관련 애노테이션만 추가하면 auto-scan되어 빈이 등록된다.
@Component, @Bean의 차이점
Component와 Bean을 사용하여 등록하는 방법의 차이점을 알아보았다.
1. @Component
- 개발자가 직접 컨트롤이 가능한 class들을 등록할 때 사용된다.
- Class Level에서 적용된다.
2. @Bean
- 개발자가 컨트롤이 불가능한 외부 라이브러리들을 Bean으로 등록하고 싶은 경우에 사용된다.
- Method Level에서 적용된다.
[Reference]
- 인프런 - 김영한님의 스프링 핵심 원리 기본편
'Backend > Spring' 카테고리의 다른 글
Spring Transactional Isolation (0) | 2023.01.04 |
---|---|
Spring Transactional Propagation (0) | 2022.12.28 |
스프링 빈(Bean) (0) | 2021.08.20 |
빈 스코프(Bean Scope) (0) | 2021.08.20 |
[Spring security password Encoding] Spring boot 패스워드 간단 암호화 (0) | 2021.05.23 |