관리 메뉴

JIE0025

[Spring] 스프링 빈(bean), 스프링 컨테이너, 빈 등록하는 방법 본문

백엔드/스프링, 스프링부트, JPA, Spring Webflux

[Spring] 스프링 빈(bean), 스프링 컨테이너, 빈 등록하는 방법

Kangjieun11 2022. 11. 23. 23:10
728x90



개인적으로 공부하면서 정리한 내용입니다 : )






FLAG Project - BE Study 

2022.11.10





FLAG








스프링 빈(bean)

  • 스프링 빈 (bean)
  • 스프링 컨테이너 (container)
  • 빈을 컨테이너에 등록하는 방법
    • 컴포넌트 스캔   (@component)
    • 스프링 빈 직접 등록


스프링 빈 (bean)

빈(bean) : 스프링 컨테이너가 관리하는 자바객체

스프링의 특징 중 <제어의 역전(IOC)> 이 있는데,
객체의 생성과 제어권을 사용자가 아닌 스프링에게 맡기는 것을 의미한다.

지금까지 사용자가 new 연산으로 객체를 생성하고 메서드를 호출했는데 IoC가 적용되면 객체의 생성과 제어권을 스프링에게 넘겨준다. 사용자는 직접 new를 이용해 생성된 객체를 사용하지 않고, 스프링에 의해 관리당하는 자바 객체를 사용하게 되는데 이 객체가 바로 빈(bean)이다.

스프링 컨테이너 (Container)

스프링에서 자바 객체들을 관리하는 공간
빈의 생성부터 소멸까지 개발자 대신 관리해준다.


⏺ 스프링 컨테이너의 종류

  • BeanFactory
  • ApplicationContext  (대부분 이걸 사용)
    •  BeanFactory 기능을 포괄  + 추가 기능 제공
    • 구현체 :   AnnotationConfigApplicationContext()  

스프링 컨테이너에 객체(빈)을 등록하는 이유

스프링이 각 객체간 의존관계를 관리하도록 하는데에 큰 목적이 있음
객체가 의존관계를 등록할 때는 스프링 컨테이너에서 해당하는 빈을 찾고, 그 빈과 의존성을 만든다.


스프링 빈 등록

컴포넌트 스캔

@Component를 가진 모든 대상을 가져와서 빈에 등록하기 위해 찾는 과정

✔️ 컴포넌트 스캔 대상

    • @Component : 컴포넌트 스캔에서 사용
    • @Controller : 스프링 MVC 컨트롤러에서 사용
    • @Service : 스프링 비즈니스 로직에서 사용
    • @Repository : 스프링 데이터 접근 계층에서 사용
    • @Configuration : 스프링 설정 정보에서 사용

* 스프링 프레임워크에서 제공하는 @Controller나 @Service 혹은 @Repository와 같은 Annotation은
아래와 같이 인터페이스로 @Component Annotation을 받기 때문에 컴포넌트 등록이 가능하다.

@Component
public @interface Service {
	...
}

* 빈 설정파일 + @Bean을 통해 빈을 하나하나 지정할 필요가 없음

◼️ 자동 의존관계 주입

스프링 빈 설정 파일이 없어진다면 해당 파일에서 해주던 의존관계 주입을 해주는 것이 필요하다
>>> @Autowired : 타입 으로 의존성 주입
>>> @Resource : 변수와 setter메서드를 빈 이름 으로 자동 연결 -> 여러 인수 받는 메서드는 불가능

◼️ @Autowired

스프링 DI(Dependency Injection)에서 사용되는 어노테이션
* DI - 의존성 종속 (클래스간 의존관계를 스프링 컨테이너가 자동으로 연결해주는 것)
* DI는 왜 필요할까? 객체간 의존성 때문에 -- 3가지 방법이 있는데 그중에 하나가 바로 이 @Autowired이다. 나중에 다시 이부분은 더 깊게 봐야겠다.

Factory 인터페이스를 상속받는 ConsoleFactory, UserFactory가 있다 가정
고객은 Factory 클래스만을 호출해야하며, 그것이 ConsoleFactory인지 UserFactory인지 몰라야 한다.
고객마다 전용 Factory를 생성할 경우 코드 생산성이 떨어지고, 고객이 몰라도 되는 코드가 노출되기 때문이다.

이 때문에 스프링은 Factory가 ConsoleFactory인지 UserFactory인지를 프레임워크가 자동으로 객체간 의존성을 주입해준다.



스프링에서 빈 인스턴스가 생성된 이후 @Autowired를 설정한 메서드가 자동으로 호출되고,
인스턴스가 자동으로 주입됨

* 변수, 생성자, Setter메서드, 일반메서드 등에 적용 가능함.

◼️ @Resouce

@Autowired 가 Type으로 찾아서 주입하므로,
동일한 Bean 타입의 객체가 여러개 있을 경우
Bean을 찾기 위해 @Qualifier 어노테이션을 같이 사용해줌

* 변수, Setter메서드 등에 적용 가능
* 빈이 Map타입인 경우 @Autowired말고 @Resource를 사용해야함.


<context:component scan > 태그
@Autowired로 의존 관계를 주입받을 경우,
해당 클래스(@Autowired당하는 클래스)를 반드시 Component Auto Scanning을 설정해야 함

🔽 Component Auto Scanning 코드 🔽

<context:component-scan base-package="factory.userfactory" />


결국..

1) 스프링 컨테이너가 @Component를 찾아 모두 스프링 빈으로 등록!
2) 의존성이 필요한 부분에서 @Autowired 태그가 있다면 등록된 스프링 빈에서 찾아서 의존관계 주입 설정!




⏺ 스프링 빈 직접 등록


1) Appconfig 클래스에 @Configuration을 붙힌다.
2) @Bean어노테이션을 붙히면, 스프링 컨테이너에 빈으로 등록된다.

// 설정 정보라는 의미로 붙여준다.
@Configuration
public class AppConfig {

  // 스프링 컨테이너에 빈으로 등록한다.
  @Bean
  public MemberService memberService() {
    return new MemberServiceImpl(memberRepository());
  }

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

  public OrderService orderService() {
    return new OrderServiceImpl(memberRepository(), discountPolicy());
  }

  @Bean
  public DiscountPolicy discountPolicy() {
    return new RateDiscountPolicy();
  }

}

싱글톤으로 빈 등록..!

@Bean(name = "memberService2")

빈 이름의 기본 값은 메서드 이름(*가장 앞글자를 소문자로 바꿈)이지만 직접 부여할 수 있다.
* 빈 이름은 항상 다르게 부여해야함 (고유값)
** 왜 (WHY) ? 스프링은 보통의 경우 스프링컨테이너에 빈 인스턴스를 단 한개만 저장하는 싱글톤방식을 채택하고 있어서
* 만약 같은 이름 부여시 다른 빈이 무시 or 기존 빈을 덮거나, 설정에 따라 오류가 발생

스프링 빈 의존 관계 설정

컨테이너가 빈 등록한 뒤에 의존 관계를 넣어줘야한다.

설정 정보를 참고하며 memberService와 orderService의 의존관계에 memberRepository를 넣어줌.

⏺ 스프링 컨테이너를 통해 빈 찾기

applicationContext.getBean()

- ac.getBean(class타입)
- ac.getBean(빈이름, class타입)
- ac.getBean(빈이름)

조회하고자 하는 빈이 존재하지 않는 경우엔 NoSuchBeanDefinitionException 예외가 발생

컨테이너에 객체를 빈으로 등록해 찾아 사용할수 있다.!!!
이젠 객체에 대한 관리를 내가 안한다 !


references

'백엔드 > 스프링, 스프링부트, JPA, Spring Webflux' 카테고리의 다른 글

[Spring] DI/ IOC  (0) 2022.12.08
[Spring] Annotation  (0) 2022.11.24
[Spring] QueryDSL  (0) 2022.11.13
[JPA] 3장 영속성 관리  (0) 2022.11.05
[JPA] JPQL 개념, 기본 기능  (0) 2022.10.27