스프링 컨테이너는 스프링 프레임워크 내에서 개발자가 정의한 객체(빈)을 생성하고 관리하고 제공해주는 역할을 한다.스프링이라는 프레임워크에서 이거하라고 만들어둔 도구임 "아~ 이거 약간 개?념쪽? 이구나?" 가 아니라 도구야 도구~ 핵심적인 내용을 요약하자면
의존성 주입(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
를 통해 객체를 생성해줌. "근데 걍 new
로 MemberService
나 OrderService
객체 생성하면되지않음?" 할 수 있는데 그건 서로를 참조하게됨. 즉? 책임을 명확히 하기위해서는 역할을 분리시켜야함.
왜 이렇게 분리를 시켜놓냐? 그건 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 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에 관한 내용으로 빠지는거같으니 여기까지만 하겠다! 그 뒤부터는? 이전에 올렸던 포스팅과 동일하므로 생략 ㅎㅎ;
핵심을 요약하자면? BeanFactory
와 ApplicationContext
컨테이너로 대부분의 기능을 편리하게 이용할수있다는것과 이로인해 스프링 컨테이너는 모듈성과 유지보수성이 뛰어나기때문에 애플리케이션을 개발하는 데 큰 도움을 준다! 라는것!