의존 관계
public interface DiscountPolicy {
int discount(Member member, int price);
}
public class FixDiscountPolicy implements DiscountPolicy {
private int discountFixAmount = 1000;
@Override
int discount(Member member, int price) {
if (member.getGrade() == Grade.VIP) {
return discountFixAmount;
} else {
return 0;
}
}
}
public class RateDiscountPolicy implements DiscountPolicy {
private int discountPercent = 10;
@Override
int discount(Member member, int price) {
if (member.getGrade() == Grade.VIP) {
return price * discountPercent / 100;
} else {
return 0;
}
}
}
// Test 작성을 VIP일 때와 아닐 때를 테스트 해보면 좋다
public class AppConfig {
// 이거보다는
public MemberService memberService() {
return new MemberServiceImpl(new MemoryMemberRepository());
}
// 이게좋다
public MemberService memberService() {
return new MemberServiceImpl(memberRepository());
}
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
// 할인 정책 예시를 통해 좋은 점을 확인할 수 있는데
public DiscountPolicy discountPolicy() {
// return new FixDiscountPolicy();
return new RateDiscountPolicy();
} // 이런식으로 입맛대로 교체가 가능해짐
}
스프링 빈 상속 관계
@Configuration
static class TestConfig {
@Bean
public DiscountPolicy rateDiscountPolicy() {
return new RateDiscountPolicy();
}
@Bean
public DiscountPolicy rateDiscountPolicy() {
return new FixDiscountPolicy();
}
}
@Test
@DisplayName("부모 타입으로 조회시, 자식이 둘 이상 있으면, 중복 오류가 발생")
@Test
@DisplayName("부모 타입으로 조회시, 자식이 둘 이상 있으면, 빈 이름을 지정하면 됌")
스프링 컨테이너 생성
ApplicationContext applicationContext =
new ApplicationConfigApplicationContext(AppConfig.class);
- ApplicationContext가 스프링 컨테이너 & 인터페이스
- 스프링 컨테이너는 XML, 애노테이션 기반 설정 클래스로 만들 수 있음
// 테스트
ApplicationContextTest {
AnnotationConfigApplicationContext ac =
new AnnotationConfigApplicationContext(AppConfig.class);
@Test
@DisplayName("모든 빈 출력/애플리케이션 빈") // 테스트시 나오는 이름
void findAllBean() {
String[] beanDefinitionNames = ac.getBeanDefinitionNames(); // 스프링에 등록된 모든 빈 이름을 조회
iter {
Object bean = ac.getBean(beanDefinitionName); // 빈 이름으로 빈 객체를 조회
}
iter {
BeanDefinition beanDefinition = ac.getBeanDefinition(beandDefinitionName);
// ROLE_APPLICATION: 일반적으로 사용자가 정의한 빈
// ROLE_INFRASTRUCTURE: 스프링이 내부에서 사용하는 빈
if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {
Object bean = ac.getBean(beanDefinitionName);
}
}
}
@Test
@DisplayName("빈 이름/구체타입 조회")
void findBeanByName() {
UserService userService = ac.getBean("userService", UserService.class);
assertThat(userService).isInstanceOf(UserServiceImpl.class);
UserServiceImpl userService = ac.getBean("userService", UserServiceImpl.class);
assertThat(userService).isInstanceOf(UserServiceImpl.class);
}
@Test
@DisplayName("빈 없")
void findBeanByNameX() {
Assertions.assertThrows(NoSuchBeanDefinitionException.class, () ->
ac.getBean("xxxx", UserService.class));
}
}
동일한 타입이 둘 이상
@Configuration
static SameBeanConfig {
@Bean
public UserRepository userRepository1() {
return new MemoryUserRepository();
}
@Bean
public UserRepository userRepository2() {
return new MemoryUserRepository();
}
@Test
@DisplayName("타입으로 조회시 같은 타입이 둘 이상 있으면, 중복 오류가 발생")
@Test
@DisplayName("타입으로 조회시 같은 타입이 둘 이상 있으면, 빈 이름을 지정하면 됌")
@Test
@DisplayName("특정 타입을 모두 조회하기")
void findAllBeanByType() {
Map<String, UserRepository> beansOfType = ac.getBeansOfType(UserRepository.class);
iter (beansOfType.keySet()) {
print(key)
}
}
}
'Spring > Basic' 카테고리의 다른 글
[Basic] 싱글톤 컨테이너 (0) | 2024.08.27 |
---|---|
[Basic] BeanFactory / ApplicationContext (0) | 2024.08.27 |
[Basic] 간단하게 기억할 내용 (0) | 2024.08.21 |
[Basic] Tomcat 직접 등록을 통한 환경 세팅 방법 (0) | 2024.08.09 |
[Basic] 웹 스코프 (0) | 2024.04.07 |