Spring 핵심 원리 TIL (5)

YulHee Kim·2021년 8월 24일
0

Spring 핵심 원리

목록 보기
6/13
post-thumbnail

[참고 강의] 김영한님의 스프링 핵심 원리 - 기본편

지금까지 순수한 자바 코드만으로 DI를 적용했다.
이제 스프링으로 코드를 변경해보겠다.

💡 스프링으로 전환하기

✏️ AppConfig 스프링 기반으로 변경

  • AppConfig에 설정을 구성한다는 @Configuration을 붙여준다
  • 각 메서드에 @Bean을 붙여준다 !

AppConfig

@Configuration
public class AppConfig {

      @Bean
      public MemberService memberService() {
          return new MemberServiceImpl(memberRepository());
      }
      @Bean
      public OrderService orderService() {
          return new OrderServiceImpl(
                  memberRepository(),
                  discountPolicy());
     }
      @Bean
      public MemberRepository memberRepository() {
          return new MemoryMemberRepository();
      }
      @Bean
      public DiscountPolicy discountPolicy() {
         return new RateDiscountPolicy();
	} 
}

MemberApp에 스프링 컨테이너 적용

public class MemberApp {
      public static void main(String[] args) {
  //        AppConfig appConfig = new AppConfig();
  //        MemberService memberService = appConfig.memberService();
          ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
          MemberService memberService = applicationContext.getBean("memberService", MemberService.class);
          Member member = new Member(1L, "memberA", Grade.VIP);
          memberService.join(member);
          Member findMember = memberService.findMember(1L);
          System.out.println("new member = " + member.getName());
          System.out.println("find Member = " + findMember.getName());
 	}
}

OrderApp에 스프링 컨테이너 적용


public class OrderApp {

	public static void main(String[] args) {
           // AppConfig appConfig = new AppConfig();
           // MemberService memberService = appConfig.memberService();
           // OrderService orderService = appConfig.orderService();
           
              ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
              MemberService memberService = applicationContext.getBean("memberService", MemberService.class);
              OrderService orderService = applicationContext.getBean("orderService", OrderService.class);
              
              long memberId = 1L;
              Member member = new Member(memberId, "memberA", Grade.VIP);
              memberService.join(member);
              Order order = orderService.createOrder(memberId, "itemA", 10000);
              
              System.out.println("order = " + order);
       }
}

✏️ 스프링 컨테이너

  • ApplicationContext를 스프링 컨테이너라 한다.
  • 이 컨테이너가 DI를 할 수 있게 한다.
  • 스프링 컨테이너는 @Configuration이 붙은 @AppConfig를 설정(구성) 정보로 사용한다.
  • 여기서 @Bean이 적힌 스프링 빈(memberService, orderService)을 모두 호출해 반환된 객체를 스프링 컨테이너에 등록한다.
  • 필요한 객체를 스프링 컨테이너를 통해서 스프링 빈(객체)를 찾아야한다.
  • 스프링 빈은 applicationContext.getBean()메서드를 사용해서 찾을 수 있다.

💡 스프링 컨테이너와 스프링 빈

스프링 컨테이너 생성

스프링 컨테이너가 생성되는 과정을 알아보자.

ApplicationContext applicationContext =
           new AnnotationConfigApplicationContext(AppConfig.class);
  • ApplicationContext를 스프링 컨테이너라 한다.
  • ApplicationContext는 인터페이스이다.
  • 자바 설정 클래스 기반으로 스프링 컨테이너를 만들면 위 코드와 같다.
  • AnnotationConfigApplicationContext 클래스는 ApplicationContext 인터페이스의 구현체이다.

스프링 컨테이너의 생성 과정

스프링 컨테이너 생성

new AnnotationConfigApplicationContext(AppConfig.class)

  • 스프링 컨테이너를 생성할 때는 구성 정보(AppConfig.class)를 지정해주어야 한다.

스프링 빈 등록

  • 스프링 컨테이너는 파라미터로 넘어온 설정 클래스 정보를 사용해서 스프링 빈을 등록한다.
  • 빈 이름은 메서드 이름을 사용한다
  • 빈 이름을 직접 부여할 수도 있다. Bean(name="memberService2")
    빈 이름은 항상 다른 이름을 부여해야 한다.
  • 스프링 컨테이너는 설정 정보를 참고해서 의존관계를 DI한다.

✏️ 컨테이너에 등록된 모든 빈 조회

스프링 컨테이너에 실제 스프링 빈들이 잘 등록되었는지 확인해보겠다 😎

class ApplicationContextInfoTest {

      AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
      
      @Test
      @DisplayName("모든 빈 출력하기")
      void findAllBean() {
          String[] beanDefinitionNames = ac.getBeanDefinitionNames();
          for (String beanDefinitionName : beanDefinitionNames) {
              Object bean = ac.getBean(beanDefinitionName);
              System.out.println("name=" + beanDefinitionName + " object=" + bean);
	   }    
	}
		
       @Test
       @DisplayName("애플리케이션 빈 출력하기") 
       void findApplicationBean() {
          String[] beanDefinitionNames = ac.getBeanDefinitionNames();
          for (String beanDefinitionName : beanDefinitionNames) {
              BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);

              if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {
              	Object bean = ac.getBean(beanDefinitionName);
              	System.out.println("name=" + beanDefinitionName + " object=" +
               }
           }
      }
   }
  • ac.getBeanDefinitionNames() : 스프링에 등록된 모든 빈 이름을 조회한다.
  • ac.getBean() : 빈 이름으로 빈 객체(인스턴스)를 조회한다.
  • 스프링이 내부에서 사용하는 빈은 getRole()로 구분할 수 있다.
    • ROLE_APPLICATION : 일반적으로 사용자가 정의한 빈
    • ROLE_INFRASTRUC : 스프링이 내부에서 사용하는 빈

profile
백엔드 개발자

0개의 댓글