해당 내용은
https://velog.io/@dlsrjsdl6505/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EC%9D%B4%ED%95%B4-%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5-%EC%9B%90%EB%A6%AC-%EC%A0%81%EC%9A%A9
의 내용에 이어져 설명됩니다! :)
이전에 만든 AppConfig 클래스를 기반으로,
애노테이션 기반(@Configuration, @Bean)
의 자바 설정 클래스로 스프링 컨테이너를 생성했다.
코드는 Spring이 AppConfig 클래스를 구성 정보로 인식하고
스프링 컨테이너를 만들 수 있도록 작성했다.
(ApplicationContext 객체가 스프링 컨테이너)
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
@Configuration
public class AppConfig {
@Bean
public MemberService memberService(){
return new MemberServiceImpl(memberRepository());
}
@Bean
public MemoryMemberRepository memberRepository() {
return new MemoryMemberRepository();
}
@Bean
public OrderService orderService(){
return new OrderServiceImpl(memberRepository(), discountPolicy());
}
@Bean
public DiscountPolicy discountPolicy(){
return new RateDiscountPolicy();
}
}
해당 코드를 통해, 스프링 컨테이너에서
@Bean이 붙은 객체들을 기준으로
객체를 생성하고 의존관계도 설정해준다.
위에서,
ApplicationContext 객체가 스프링 컨테이너라고 했다.
그럼 BeanFactory는 뭘까?
똑같은 컨테이너이다.
상속 관계는 위와 같다.
상속 관계를 보면, ApplicationContext에는
BeanFactory의 기능에, 더 많은 기능이 추가되있는 것을 알 수 있다.
ApplicationContext에서 추가되는 기능들의 예시는 다음과 같다.
메세지소스를 활용한 국제화 기능
(한국에서 들어오면 한국어로, 영어권에서 들어오면 영어)
환경변수
(로컬, 개발, 운영등을 구분해서 처리)
애플리케이션 이벤트
(이벤트를 발행하고 구독하는 모델을 편리하게 지원)
편리한 리소스 조회
(파일, 클래스패스, 외부 등에서 리소스를 편리하게 조회)
또한,
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
지금은 위의 코드를 통해 AppConfig 클래스를 기반으로 컨테이너를 생성하지만,
AppConfig.class
를 AppConfig.xml
으로 교체하여
xml형식으로도 Config를 작성할 수 있다.
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="hello.core.member.MemberServiceImpl">
<constructor-arg name="memberRepository" ref="memberRepository" />
</bean>
<bean id="memberRepository"
class="hello.core.member.MemoryMemberRepository" />
<bean id="orderService" class="hello.core.order.OrderServiceImpl">
<constructor-arg name="memberRepository" ref="memberRepository" />
<constructor-arg name="discountPolicy" ref="discountPolicy" />
</bean>
<bean id="discountPolicy" class="hello.core.discount.RateDiscountPolicy" />
</beans>
그러면, 구성 내용을 위와 같이
AppConfig.class, xml 등등으로 만들어내면,
해당 내용을 기반으로
@Bean 단위마다
설정 메타정보, 즉 BeanDefinition이 생성된다.
스프링 컨테이너는 이 BeanDefinition을 기반으로
Spring Bean을 생성한다.
해당 내용은 아래와 같다.
AppConfig.class를 기준으로 설명을 하겠다.
우리는 @Configuration, @Bean을 사용해 컨테이너와 빈을 등록했다.
이렇게 어노테이션을 사용할때는,
AnnotationConfigApplicationContext 가
AnnotatedBeanDefinitionReader을 이용하여
AppConfig.class 를 읽고 BeanDefinition 을 생성한다.
해당 BeanDefinition을 기반으로 빈들을 만들고 컨테이너를 생성한다.
Spring을 이용하여 프로젝트를 진행하는것과,
그 내부가 어떻게 동작되는지를 이해하는 일은 또다른 일이다.
보통 우리가 사용하는 @Service, @Repository, @RestController
이러한 어노테이션들 또한 빈이고,
해당 빈들을 컨테이너에서 관리한다.
위에서는 컨테이너를
ApplicationContext라는클래스로 생성해서 봤지만,
실제 프로젝트에선 컨테이너와 빈을
@SpringBootApplication
안의
아래 어노테이션을 통해 자동으로 처리해준다.
@Configuration: 클래스 내부에 빈 정의와 설정을 위한 메서드 제공.
@EnableAutoConfiguration: Spring Boot의 자동 설정 기능을 활성화. 이를 통해 애플리케이션의 클래스패스와 설정에 기반하여 자동으로 빈들을 등록하고 설정.
@ComponentScan: 컴포넌트들을 스캔하여 빈으로 등록.
소스코드 : https://github.com/ingeon2/coreofspring-SOLID
레퍼런스 : 김영한님 pdf