[Spring] 스프링 컨테이너

이신영·2024년 1월 14일
1

Spring

목록 보기
7/16
post-thumbnail

스프링 컨테이너란?

스프링 컨테이너는 스프링 프레임워크 내에서 개발자가 정의한 객체(빈)을 생성하고 관리하고 제공해주는 역할을 한다.스프링이라는 프레임워크에서 이거하라고 만들어둔 도구임 "아~ 이거 약간 개?념쪽? 이구나?" 가 아니라 도구야 도구~ 핵심적인 내용을 요약하자면

  • 의존성 주입(Dependency Injection): 스프링 컨테이너는 객체 간의 의존성을 관리하고, 필요한 의존 객체를 주입해주는 역할을 한다. 이를 통해 객체 간의 결합도를 낮추고 유연한 애플리케이션을 개발할 수 있다.

  • Bean 관리: 스프링은 빈(Bean)이라 불리는 객체들을 생성하고 관리한다. 빈은 스프링 컨테이너에 의해 생성되고, 빈의 라이프사이클 관리도 스프링이 담당한다.

  • IoC (Inversion of Control): 제어의 역전으로도 알려진 IoC는 개발자가 코드를 작성하면서 객체의 생성이나 생명주기 관리를 개발자가 하는 것이 아니라, 스프링 컨테이너가 이를 대신 수행하는 개념

이라고 볼 수 있다.

@SpringBootApplication
public class Study1Application {

	public static void main(String[] args) {
		SpringApplication.run(Study1Application.class, args);
	}

}

위 코드는 스프링 부트 애플리케이션을 시작하는 기본적인 코드이다. 아직 스프링의 초급자가 본다면 위 코드가 얼마나 축약된건지 모를것이다..! (나도 몰랐었거든요 ㅎㅎ..) 그렇다면 스프링 컨테이너가 뭔지, 어떻게 기술이 편리해졌는지에대해 알아보기위해 코드로 알아보도록하자! (이 강의를 기반으로함) 만약 스프링을 독학중인 당신? 지금바로 구매권장.. 커리큘럼이 진짜 중요하더라구요 😂 독학 진짜 힘듦..

초기의 스프링 컨?테이너

public class AppConfig {

    public MemberService memberService() {
        return new MemberServiceImpl(memberRepository());
    }
        
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }
    
    public OrderService orderService() {
        return new OrderServiceImpl(
                memberRepository(),
                discountPolicy());
    }
    
    public DiscountPolicy discountPolicy() {
        return new FixDiscountPolicy();
    }
}
public class OrderApp {
    public static void main(String[] args) {
        AppConfig appConfig = new AppConfig();
        MemberService memberService = appConfig.memberService();
        OrderService orderService = appConfig.orderService();

        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);
    }
}

스프링을 쓰지않고 구현된 예시인데 AppConfig에 모든 서비스를 넣어두고 어플리케이션 OrderApp에서 AppConfig를 통해 객체를 생성해줌. "근데 걍 newMemberServiceOrderService 객체 생성하면되지않음?" 할 수 있는데 그건 서로를 참조하게됨. 즉? 책임을 명확히 하기위해서는 역할을 분리시켜야함.

  • AppConfig = 무대기획
  • MemberService, OrderService = 배우
  • MemberServiceImple, OrderServiceImpl = 배역

왜 이렇게 분리를 시켜놓냐? 그건 SOLID 원칙을 위반하지 않기위해서이다!


이제야 좀 스프링 컨테이너

@Configuration
public class Appconfig {

    @Bean
    public MemberService memberService() {
        return new MemberServiceImpl(memberRepository());
    }

    @Bean
    public static MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }

    @Bean
    public OrderService orderService() {
        return new OrderServiceImpl(
                memberRepository(),
                discountPolicy());
    }
    @Bean
    public DiscountPolicy discountPolicy(){
        return new RateDiscountPolicy();
    }
}
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;
        Long memberId2 = 2L;

        Member member1 = new Member(memberId, "memberA", Grade.VIP);
        Member member2 = new Member(memberId2, "memberB", Grade.BASIC);
        memberService.join(member1);
        memberService.join(member2);
        Order order = orderService.createOrder(memberId, "itemA", 11000);
        Order order2 = orderService.createOrder(memberId2, "itemB", 50000);
        System.out.println("order = " + order.toString());
        System.out.println("order = " + order.calculatePrice() + "원" );
        System.out.println("order2 = " + order2.toString());
        System.out.println("order2 = " + order2.calculatePrice()+ "원");
    }
}

이제야 막~ 골뱅이 붙고 그러죠? 이건 어노테이션 이라는건데 이거모르면 일단 다른곳가서 검색하고오시고 여기서 중요한건

  • AppConfig로 모든 객체를 생성해주는게아니라 ApplicationContext applicationContext를 통해 생성시키고 AppConfig를 넘겨주고있다는거?
  • @Bean으로 객체를 관리하고있다는거?

아직까지는 막 와 스프링! 와! 편하다! 까진 아니죠? ㅎㅎ


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="lsy.study_1.member.MemberServiceImpl">
        <constructor-arg name="memberRepository" ref="memberRepository" />
    </bean>
    <bean id="memberRepository" class="lsy.study_1.member.MemoryMemberRepository"/>

    <bean id="orderService" class="lsy.study_1.order.OrderServiceImpl">
        <constructor-arg name="memberRepository" ref="memberRepository"/>
        <constructor-arg name="discountPolicy" ref="discountPolicy"/>
    </bean>

    <bean id="discountPolicy" class="lsy.study_1.discount.RateDiscountPolicy"/>

</beans>
public class xmlApp {
    public static void main(String[] args) {
        ApplicationContext ac = new GenericXmlApplicationContext("appConfig.xml");
        MemberService memberService = ac.getBean("memberService", MemberService.class);
        OrderService orderService = ac.getBean("orderService", OrderService.class);

        Long memberId = 1L;
        Long memberId2 = 2L;

        Member member1 = new Member(memberId, "memberA", Grade.VIP);
        Member member2 = new Member(memberId2, "memberB", Grade.BASIC);
        memberService.join(member1);
        memberService.join(member2);
        Order order = orderService.createOrder(memberId, "itemA", 11000);
        Order order2 = orderService.createOrder(memberId2, "itemB", 50000);
        System.out.println("order = " + order.toString());
        System.out.println("order = " + order.calculatePrice() + "원" );
        System.out.println("order2 = " + order2.toString());
        System.out.println("order2 = " + order2.calculatePrice()+ "원");

    }
}

씁.. 갑분XML... 으 하기싫어... 할수있지만..!? 일단 XML로도 빈을 등록할 수 있다! 는 알아두자!

컴서운사실) 회사의 오래된 프로젝트는 아직도 이걸 쓰는곳이 있다고 한다..

바뀐건 이건데 약간 번외 느낌으로 알아두는걸로

  • GenericXmlApplicationContext으로 appConfig.xml를 넘겨줌

점점 DI에 관한 내용으로 빠지는거같으니 여기까지만 하겠다! 그 뒤부터는? 이전에 올렸던 포스팅과 동일하므로 생략 ㅎㅎ;

핵심을 요약하자면? BeanFactoryApplicationContext 컨테이너로 대부분의 기능을 편리하게 이용할수있다는것과 이로인해 스프링 컨테이너는 모듈성과 유지보수성이 뛰어나기때문에 애플리케이션을 개발하는 데 큰 도움을 준다! 라는것!

profile
후회하지 않는 사람이 되자 🔥

0개의 댓글