Spring

Spring Bean

muyeon 2024. 1. 16. 23:29

빈은 스프링 컨테이너에 의해 관리되는 재사용 가능한 소프트웨어 컴포넌트이다.

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

스프링 컨테이너가 관리하는 자바 객체를 뜻하며, 하나 이상의 빈을 관리한다.

 

빈은 인스턴스화 된 객체를 의미하고, 스프링 컨테이너에 등록된 객체를 스프링 빈이라고 한다.

@Bean 어노테이션을 통해 메서드로부터 반환된 객체를 스프링 컨테이너에 등록한다.

빈은 클래스의 등록 정보, Getter/Setter 메서드를 포함하며, 컨테이너에 사용되는 설정 메타데이터로 생성된다.

 

설정 메타데이터 : XML or Java Annotation, 자바 코드로 표현하며 컨테이너의 명광과 인스턴스화, 설정, 조립할 객체 등을 정의한다.

 


IoC 의 특징

 

일반적으로 처음 배우는 자바 프로그램에서는 각 객체들이 프로그램의 흐름을 결정하고 각 객체를 직접 생성하고 조작하는 작업(객체를 직접 생성하여 메서드 호출)을 했다. 즉 모든 작업을 사용자가 제어하는 구조였다.

ex) A 객체에서 B 객체에 있는 메서드를 사용하고 싶다면, B 객체를 직접 A 객체 내에서 생성하고 메서드를 호출

 

IoC 가 적용된 경우, 객체의 생성을 특별한 관리 위임 주체에게 맡긴다. 이 경우 사용자는 객체를 직접 생성하지 않고, 객체의 생명주기를 컨트롤하는 주체는 다른 주체가 된다. 

사용자의 제어권을 다른 주체에게 넘기는 것을 IoC(제어의 역전)라고 한다.

 

Spring 에서는 직접 new 를 이용하여 생성한 객체가 아니라, Spring 에 의해 관리당하는 자바 객체를 사용한다.

이렇게 Spring에 의해 생성되고 관리되는 자바 객체를 Bean 이라고 한다.

 


Bean 을 왜 사용할까?

 

스프링 간 객체의 의존관계를 관리하도록 하는 것에 가장 큰 목적이 있다.

객체가 의존관계를 등록할 때 스프링 컨테이너에서 해당하는 빈을 찾고, 그 빈과 의존성을 만든다.

 


Spring Bean의 생명주기

 

객체 생성 -> 의존 설정 -> 초기화 -> 사용 -> 소멸 과정 의 생명주기를 가지고 있다.

 

빈은 스프링 컨테이너에 의해 생명주기를 관리한다.

스프링 컨테이너가 초기화될 때 먼저 빈 객체를 설정에 맞추어 생성하며 의존 관계를 설정한 뒤 해당 프로세스가 완료되면 빈 객체가 지정한 메서드를 호출해서 초기화를 진행한다.

객체를 사용해 컨테이너가 종료될 때 빈이 지정한 메서드를 호출해 소멸 단계를 거친다.

 

스프링은 InitializingBean 인터페이스와 DisposableBean 을 제공하며 빈 객체의 클래스가 InitializingBean Interface 또는 DisposableBean 을 구현하고 있으며 해당 인터페이스에서 정의된 메서드를 호출해 빈 객체의 초기화 또는 종료를 수행한다.

 

어노테이션을 이용한 빈 초기화 방법에는 @PostConstruct 와 빈 소멸에서는 @PreDestroy 를 사용한다.

 


Spring Bean 의 Scope

 

빈 스코프는 기본적으로 빈이 존재하는 범위를 뜻한다.

빈의 객체는 기본적으로 싱글톤의 범위를 가지며 싱글톤은 스프링 컨테이너의 시작과 종료까지 단 하나의 객체만을 사용하는 방식이다.

request, session, global session 의 스코프는 일반 spring 어플리케이션이 아니라 Spring MVC Web Application 에만 사용된다.

 

스코프 설명
singleton 하나의 빈 정의에 대해 Spring IoC Container 에서 단 하나의 객체만 존재한다.
prototype 하나의 빈 정의에 대해 다수의 객체가 존재할 수 있다.
request 하나의 빈 정의에 대해 하나의 HTTP request 의 생명주기 안에 단 하나의 객체만 존재한다. 
각각의 HTTP request는 자신만의 객체를 가지며 Web-aware Spring ApplicationContext 안에서만 유효한 특징이 있다.
session 하나의 빈 정의에 대해 하나의 HTTP Session의 생명주기 안에서 단 하나의 객체만 존재한다.
Web-aware Spring ApplicationContext 안에서만 유효한 특징이 있다.
global session 하나의 빈 정의에 대해 하나의 global HTTP Session의 생명주기 안에서 단 하나의 객체만 존재한다.
일반적으로는 portlet context 안에서만 유효하며, Web-aware Spring ApplicationContext 안에서만 유효한 특징이 있다.

 

빈의 객체 범위를 prototype 으로 설정하면 객체를 매번 새롭게 생성한다는 특징이 있으며, 프로토타입으로 설정하면 @Scope 어노테이션을 @Bean 어노테이션과 함께 사용해야 한다.

 

1. Singleton

  • singleton bean 은 스프링 컨테이너 안에서 딱 한 번 생성되며, 컨테이너가 사라질 때는 bean도 같이 사라진다.
  • 생성된 하나의 인스턴스는 single bean cache 에 저장되며 해당 bean 에 대한 요청과 참조가 있을 때마다 캐시된 객체를 반환한다.
  • 기본적으로 모든 bean 은 scope 가 명시적이지 않으면 singleton scope 를 가진다.
  • 상태가 없는 공유객체, 읽기 전용으로만 상태를 가진 객체, 쓰기가 가능한 상태를 지니면서도 사용 빈도가 높은 객체가 싱글톤 타입에 적합하다.
// xml setting
<bean id="..." class="..." scope="singleton"></bean>

// annotation setting 
@Scope("singleton")

 

2. Prototype

  • prototype bean 은 모든 요청에서 새로운 객체로 생성하는 것이며, 의존성 관계의 bean 이 주입될 때마다 새로운 객체가 생성되어 주입된다.
  • GC에 의해 bean 이 자동으로 제거된다.
  • 사용할 때마다 상태가 달라져야 하는 객체와 쓰기가 가능한 상태가 있는 객체가 프로토 타입으로 적합하다.
// xml setting
<bean id="...' class="..." scope="prototype"></bean>

// annotation setting
@Scope("prototype")

 


Spring Bean 을 Spring IoC Container 에 등록하는 방법

 

자바 어노테이션을 사용한다.

 

자바에서는 Annotation 이라는 기능이 있는데 이는 자바 소스 코드에 추가하여 사용할 수 있는 메타데이터의 일종이다.

자바에서는 @Override, @Deprecated 와 같은 기본적인 Annotation 을 제공한다. 

 

public class Parant {
	public void doSomething() {
    	System.out.println("Parent");
    }
}

Public class Son extends Parant {
    @Override
    public void doSomething() {
    	System.out.println("Son");
    }
}

 

 

스프링에서는 여러 어노테이션을 사용하지만 빈을 등록하기 위해서는 @Component 어노테이션을 사용한다.

@Component Annotation 이 등록되어 있는 경우에는 스프링이 어노테이션을 확인하고 자체적으로 빈으로 등록한다.

 

@Controller
public class HelloController {
    @GetMapping("hello")
    public String hello(Model model) {
    	model.addAttribute("data", "This is data");
        return "hello";
    }
}

 

 

@Controller 어노테이션 내부를 확인해보면 아래와 같은 코드를 확인 할 수 있다.

@Controller 어노테이션에는 @Component 어노테이션이 있는 것을 확인 할 수 있다. 이로 인해 스프링은 해당 Controller 를 빈으로 등록한다.

 

// ...

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {

	/**
	 * The value may indicate a suggestion for a logical component name,
	 * to be turned into a Spring bean in case of an autodetected component.
	 * @return the suggested component name, if any (or empty String otherwise)
	 */
	@AliasFor(annotation = Component.class)
	String value() default "";

}

 

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

 

  • @Controller : 스프링 MVC 컨트롤러로 인식된다.
  • @Repository : 스프링 데이터 접근 계층으로 인식하고 해당 계층에서 발생하는 예외는 모두 DataAccessException 으로 변환한다.
  • @Service : 특별한 처리는 하지 않으나, 개발자들이 핵심 비즈니스 계층을 인식하는데 도움을 준다.
  • @Configuration : 스프링 설정 정보로 인식하고 스프링 빈이 싱글톤을 유지하도록 추가 처리를 한다. (물론 스프링 빈 스코프가 싱클톤이 아니라면 추가 처리를 하지 않음)

Bean Configuration File 에 직접 Bean 등록

 

@Configuration 과 @Bean 어노테이션을 이용해 빈을 등록할 수 있다.

아래처럼 사용하면 스프링 프로젝트에서의 Configuration 역할을 하는 class 를 지정할 수 있다.

해당 File 하위에 빈으로 등록하고자 하는 class 에 @Bean 어노테이션을 사용해주면 등록할 수 있다.

 

@Configuration
public class HelloConfiguration {
    @Bean
    public HelloController sampleController() {
    	return new SampleController;
    }
}

 


컴포넌트 스캔과 자동 의존관계 설정

 

컴포넌트 스캔은 @Component 를 명시하여 빈을 추가하는 방법이다.

클래스 위에 @Component 를 붙이면 스프링이 알아서 스프링 컨테이너에 빈을 등록한다.

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {

 

@Component 는 ElementType.TYPE 설정이 있어 Class 혹은 Interface 에만 붙일 수 있다.

 

 

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

 

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

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

 


@Bean vs @Component

 

@Bean

개발자가 컨트롤리 불가능한 외부 라이브러리들을 Bean 으로 등록하고 싶은 경우에 사용

메서드 또는 어노테이션 단위에 붙일 수 있다.

 

@Component

개발자가 직접 컨트롤이 가능한 클래스들의 경우에 사용된다.

클래스 또는 인터페이스 단위에 붙일 수 있다.


참고링크

 

https://ittrue.tistory.com/221

 

[Spring] 스프링 빈(Bean)이란 무엇인가?

빈(Bean) 빈(Bean)은 스프링 컨테이너에 의해 관리되는 재사용 가능한 소프트웨어 컴포넌트이다. 즉, 스프링 컨테이너가 관리하는 자바 객체를 뜻하며, 하나 이상의 빈(Bean)을 관리한다. 빈은 인스

ittrue.tistory.com

https://melonicedlatte.com/2021/07/11/232800.html

 

스프링 빈(Spring Bean)이란? 개념 정리 - Easy is Perfect

 

melonicedlatte.com

https://dev-wnstjd.tistory.com/440

 

🟢 [Spring] 스프링 빈(Bean) 이란?

📌 스프링 빈(Bean) 이란? 빈(Bean)은 스프링 컨테이너에 의해 관리되는 재사용 가능한 소프트웨어 컴포넌트이다. 즉, 스프링 컨테이너가 관리하는 자바 객체를 뜻하며, 하나 이상의 빈(Bean)을 관리

dev-wnstjd.tistory.com

https://developer-ellen.tistory.com/198

 

Spring Bean의 개념과 생성원리 및 과정

1. Spring Bean이란 ? Spring Bean은 Spring IoC 컨테이너가 관리하는 자바 객체로서 컨테이너에 의해 생명주기가 관리되는 객체를 의미한다. IoC 컨테이너 안에 들어있는 객체로 필요할 때마다 IoC 컨테이

developer-ellen.tistory.com

https://steady-coding.tistory.com/594

 

[Spring] Spring Bean 총 정리

spring-study에서 스터디를 진행하고 있습니다. 스프링 빈이란? 스프링 빈은 스프링 컨테이너에 의해 관리되는 자바 객체(POJO)를 의미한다. 스프링 컨테이너 스프링 컨테이너는 스프링 빈의 생명 주

steady-coding.tistory.com