Spring Been

coha96 ㅣ 2023. 7. 12. 17:37

Spring Been이란?

스프링(Spring) 컨테이너가 관리하는 자바 객체를 빈(Bean)이라 한다.

스프링 기술

  • 스프링 코어
    • DI, IoC, 컨테이너 : 스프링의 근간을 이루고 전체 어플리케이션을 통제하는데 활용되는 기술
    • Resource, AOP, Validation, SpEL : 많은 어플리케이션에서 공통적으로 활용하기 좋은 스프링에서 제공해주는 기능
  • 스프링 Web MVC
    • HTTP 요청/응답 처리 : Web MVC는 계속 어플리케이션이 요청 올때까지 대기를 하고 있음, 요청이 오면 그 즉시 처리를 하고 응답을 함
    • 필터, 인터셉터 : 웹에서 들어오는 요청을 필터링 하거나 공통적인 처리를 하는 용도의 기술
    • 예외처리 : 웹에서 들어온 처리를 하던 중 오류가 발생했을 때 어떻게 해야 더 안전하게 처리할 수 있을까?

DI, IoC, 컨테이너

The IoC Container :: Spring Framework

 

The IoC Container :: Spring Framework

This chapter covers Spring’s Inversion of Control (IoC) container.

docs.spring.io

 

Spring과 레고

  • 레고를 만들 때 편리한 점
    • 바닥에 넓은 판을 두고 그 위에 이것 저것 얹으면 편하다
    • 동그란 끼우는 부분이 모두 동일하므로 어떤 것들이든 서로 끼워볼 수 있다.
    • 너무 높은 자유도가 없기 때문에(오히려) 뭔가 만들기 편리하다
  • Spring을 쓰면 좋은 점
    • Spring이라는 넓은 판때기(컨테이너) 위에 내가 만드는 클래스만 얹으면 개발이 되므로 편하다
    • Spring Bean이라는 규격에 맞춰 만들기만 하면 서로가 서로를 가져다 쓰기가 좋다
    • 역설적으로 너무 자유롭진 않아서 원리를 알면 그 안에서는 만들기가 편리하다

DI (Dependence Injection)

의존성 주입

  • 의존성(A가 B를 사용한다, A가 B에 의존한다)
public class SimpleMovieLister {
	private MovieFinder movieFinder;

쉽게 말해, 한 객체에서 다른 객체를 가져다가 쓰면 의존성이다.

  • ex) 결제 서비스가 머니어댑터와 편의점 할인을 사용한다
    • 결제 서비스라는 블럭에 머니어댑터, 편의점 할인을 끼움

 

IoC (Inversion Of Control)

제어의 역전

  • 사용자가 직접 클래스를 생성하지 않고 프레임워크(스프링)가 제어하도록 함
  • 지금까지 사용자가 new 연산을 통해 객체를 생성하고 메소드를 호출했다면, IoC가 적용된 경우에는 이러한 객체의 생성과 사용자 제어권을 스프링에게 넘긴다.
  • 사용자는 직접 new를 이용해 생성한 객체를 사용하지 않고, 스프링에 의해 관리 당하는 자바 객체를 사용한다.
  • 이 객체를 Bean(빈)이라 한다.

  • 생성 전과 후에 무언가 하고 싶은게 있다면
 

Bean life cycle in Java Spring - GeeksforGeeks

A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.

www.geeksforgeeks.org


  • XML을 통한 빈 등록
    • 토비의 스프링, 스프링 3/4 시절까지 많이 사용
    • 설정이 외부로 명확히 분리된 것을 알 수 있음
    • 하지만 자동완성이나 컴파일 등으로 오타를 잡기 어렵고 타이핑 양이 많아짐
<?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="cardAdapter" class="com.example.account.service.CardAdapter"/>
    <bean id="moneyAdapter" class="com.example.account.service.MoneyAdapter"/>
    <bean id="discountByConvenience" class="com.example.account.service.DiscountByConvenience"/>
    <bean id="conveniencePayService" class="com.example.account.service.ConveniencePayService">
        <constructor-arg name="paymentInterfaceSet">
            <set>
                <ref bean="cardAdapter"/>
                <ref bean="moneyAdapter"/>
            </set>
        </constructor-arg>
        <constructor-arg name="discountInterface" ref="discountByConvenience"/>
    </bean>
</beans>

 

  • XML ComponentScan을 통한 빈 등록
    • 기본 빈 등록 방식은 클래스가 많을 경우 너무 번거로움
    • 자동으로 등록해줄 수는 없을까?
    • @Controller, @RestController, @Service, @Component, @Repository 등의 지정된 어노테이션이 붙은 클래스를 싹 빈으로 등록해주자
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://w2-2 스프링의 핵심 5
<context:component-scan base-package="com.example.account"/>
</beans>

@Component 어노테이션이 있으면 스프링 빈으로 자동 등록되는데, 

@Component를 포함하는 @Controller, @Service, @Repository 어노테이션도 스프링 빈으로 자동 등록된다.

@Controller 어노테이션을 사용하면 스프링 컨테이너 안에서 관리하에 놓이게 된다.

package hello.hellospring.controller;

import org.springframework.stereotype.Controller;

@Controller
public class MemberController {

    private final MemberService memberService = new MemberService();
   
   @Autowired
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }
}
}

스프링 컨테이너에 등록 하고 사용

→ 스프링 컨테이너에 등록하면 딱 하나만 등록된다.

@Autowired란 → 주입

 

생성자에 @Autowired가 있으면 스프링이 연관된 객체를 스프링 컨테이너에 찾아서 넣어준다.

MemberController는 스프링 컨테이너가 뜰 때 생성한다.

이 때 생성자 호출을 하는데 즉, 생성자에 @Autowired라 되어있으면 스프링 컨테이너에 있는 MemberService를 가져다가 주입시켜준다.

이렇게 객체 의존관계를 외부에서 넣어주는 것을 DI(의존성 주입)이라 한다.

 

만약 이 상태로 서버를 작동시키면 memberService가 스프링 컨테이너에 스프링 빈으로 등록되어 있지 않기 때문에 오류가 발생할 것이다.

즉 memberService도 스프링 빈으로 등록해주어야 한다.

@Service
public class MemberService {

	private final MemberRepository memberRepository;

	@Autowired
	public MemberService(MemberRepository memberRepository) {
		this.memberRepository = memberRepository;
	}
}

생성자에 @Autowired를 사용하려면 객체 생성 시점에 스프링 컨테이너에서 해당 스프링 빈을 찾아서 주입한다.

생성자가 1개만 있으면 @Autowired는 생략할 수 있다.

 

 

동일하게 memberRepository도 스프링 빈으로 등록!

@Repository
public class MemoryMemberRepository implements MemberRepository {}

  • JavaConfig를 통한 빈 등록
    • 스프링4 때부터 XML이 아닌 JavaConfig가 많이 활용되기 시작함
    • XML 설정파일이 자바 코드화 된 것
    • 자동완성, 컴파일 시 정적 분석으로 오류를 잡아줌
package com.example.account.config;

import com.example.account.service.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Arrays;
import java.util.HashSet;
@Configuration
public class ApplicationConfig {
    @Bean
    public ConveniencePayService conveniencePayService(){
        return new ConveniencePayService(
                new HashSet<>(Arrays.asList(moneyAdapter(), cardAdapter())),
                discountByConvenience()
        );
    }
    @Bean
    public CardAdapter cardAdapter() {
        return new CardAdapter();
    }
    @Bean
    public MoneyAdapter moneyAdapter() {
        return new MoneyAdapter();
    }
    @Bean
    public DiscountByConvenience discountByConvenience() {
        return new DiscountByConvenience();
    }
}

 

  • JavaConfig ComponeneScan을 통한 빈 등록
    • XML의 설정 방법
    • JavaConfig에서의 설정 방법
    • 스프링 부트에서는 이 방식이 기본적으로 적용되어 있으며, 그래서 편리하게 빈 등록 가능
@Configuration
@ComponentScan(basePackageClasses = ConvpayApplication.class)
public class ApplicationConfig {
}