[Spring] Bean

무1민·2023년 12월 7일
0

Spring

목록 보기
7/9
post-thumbnail

🎶Bean이란?

  • IoC컨테이너 안에 들어있는 객체
  • 컨테이너에 담겨있으며, 필요할 때 컨테이너에서 가져와서 사용
  • @Bean을 사용하거나 xml 설정을 통해 일반 객체를 Bean으로 등록할 수 있고, Bean으로 등록된 객체는 쉽게 주입하여 사용 가능
@Configuration
public class AppConfig {
    @Bean
    public MyBean myBean() {
        return new MyBean();
    }
}

Bean 등록 방법?

  1. @Component를 사용한다.
  • @Component가 등록되어 있는 경우 Spring이 확인하고 자체적으로 Bean으로 등록
  • @Component는 @Service, @Repository, @Controller안에 들어가 있다.
  • springboot에서는 @SpringBootApplication안에 @ComponentScan이 들어가 있고,
  • spring에서는 따로 xml 파일에서 설정한다.
<context:component-scan base-package="com.example.myapp" />
  1. @Bean명시
  • 메서드 레벨에서 Bean을 정의할 때 사용한다.
  • @Configuration 클래스가 Bean 정의를 포함하는 구성 클래스임을 나타낸다.
@Configuration
public class AppConfig {
    @Bean
    public MyBean myBean() {
        return new MyBean();
    }
}
  1. XML 파일에 명시
  • 보통 Spring Legacy에서 사용한다.
<beans>
    <bean id="myBean" class="com.example.MyBean"/>
</beans>

@Component vs @Configuration vs @Bean

@Component

  • 용도 : @Component 어노테이션은 클래스를 Spring Bean으로 표시한다. 이 어노테이션이 붙은 클래스는 Spring의 ComponentScan 매커니즘에 의해 자동으로 Bean으로 등록된다.
  • 적용 대상 : service, dao, utiliy class

@Configuration

  • 용도 : @Configuration 은 해당 클래스가 Bean 정의를 담고 있는 구성 클래스이다. 이 클래스 내에서 @Bean 어노테이션을 사용한 메서드를 정의하여 Bean을 생성하고 구성한다.
  • 적용 대상 : Bean 생성 로직이 복잡하거나 외부 라이브러리 클래스를 Bean으로 등록할 때 사용한다. ex) SecurityConfig

@Bean

  • 용도 : @Bean 어노테이션은 메서드 레벨에서 사용되며, 해당 메서드가 Bean 인스턴스를 생성하고 반환한다는 것을 나타낸다.
  • 적용 대상 : @Configuration 어노테이션이 붙은 클래스 내부에서 사용

@Autowired

  • @Autowired 는 의존성 주입을 위해 사용된다. Spring이 자동으로 의존성을 주입해야 하는 필드, 생성자 또는 메서드에 표시한다.
  • @Autowired 가 붙은 필드나 메서드, 생성자에 대해 spring 컨테이너는 타입에 맞는 Bean을 자동으로 찾아 주입한다.
@Service
public class MyService {
    @Autowired
    private MyRepository myRepository; // 필드 주입

    @Autowired
    public MyService(MyRepository myRepository) {
        // 생성자 주입
    }
}

Bean 생명 주기

  • 객체 생성 → 의존 설정 → 초기화 콜백 메서드 호출 → 사용 → 소멸 전 콜백 메서드 호출 → 소멸
  • 스프링 컨테이너에 의해 생명주기 관리
  • 스프링 컨테이너 초기화 시 빈 객체 생성, 의존 객체 주입 및 초기화
  • 스프링 컨테이너 종료 시 빈 객체 소멸

가장 처음에는 Spring IoC 컨테이너가 만들어지는 과정이 일어난다.

Spring에서 Component Scan으로 Bean등록을 시작하는 과정이다.

위와 같이 Bean으로 등록할 수 있는 어노테이션들과 설정파일들을 읽어서 IoC 컨테이너 안에 Bean으로 등록시킨다.

그리고 의존 관계를 주입하기 전의 준비 단계로 객체의 생성이 일어난다.

  • 생성자 주입 : 객체의 생성과 의존관계 주입이 동시에 일어난다.
  • Setter, Field 주입 : 객체의 생성 후에 의존 관계 주입

생성자 주입이 동시에 일어나는 이유 :

@Controller
public class CocoController {    
	private final CocoService cocoService; 
  
	//생성자 주입
	public CocoController(CocoService cocoService) {        
		this.cocoService = cocoService;
	}
}

OR

@Controller
@RequiredArgsConstructor
public class CocoController {    
	private final CocoService cocoService;
}

controller와 service의 의존관계가 존재하지 않는다면, controller 클래스는 객체 생성이 불가능함.

Bean 초기화/소멸 방법 3가지

  1. 빈 초기화 메소드에 @PostConstruct / @PreDestroy 사용
  • 빈 정의 xml에 <context:annotation-config></context:annotation-config> 추가
  • SpringBoot는 xml 파일 설정이 없어도 된다.
  1. InitializingBean 인터페이스의 afterPropertiesSet() 메소드 오버라이드
  • 스프링 초창기에 나와서 지금은 거의 사용X
  • 초기화, 소멸 메서드를 오버라이드하기 때문에 메소드 명을 변경 못함
  1. 커스텀 init() 메소드 정의
  • 빈 정의 xml에 init-method 속성으로 메소드 이름 지정
  • 또는 빈 초기화 메소드에 @Bean(init-method="init") 지정
  • 빈 지정시 initMethod랑 destroyMethod를 직접 지정해줘야 함
@Configuration
class LifeCycleConfig {     
	@Bean(initMethod = "initialize", destroyMethod = "close")    
	public ExampleBean exampleBean() {
		///
  }
}

Bean 초기화?

  • 의존성 주입 후 따로 빈 초기화 과정을 해주는 이유는 생성자가 호출이 되었을 때, bean은 초기화 전이어서 @PostConstruct를 사용하면, 의존성 주입이 끝나고 실행됨이 보장되므로, bean이 초기화 됨과 동시에 의존성을 확인할 수 있다.
  • bean LifeCycle에서 오직 한번만 수행된다. (여러 번 초기화 방지)

예시)

public class JwtProvider {
	@Value("${jwt.secret.key}")
	private String salt;

	private Key SECRET_KEY;
	
	@PostConstruct
	protected void init(){
	    SECRET_KEY = Keys.hmacShaKeyFor(salt.getBytes(StandardCharsets.UTF_8));
	}

salt값은 @Value 어노테이션을 통해 yml파일에서 주입이 됐고, init() 가 호출되는 시점에는 salt가 이미 주입이 되어 있어야함. 그래서 @PostConstruct 로 주입이 완료된 후에 호출이 되니까, salt를 안전하게 사용해서 초기화할 수 있음

또, @PostConstruct를 사용하면, 개발자는 명시적으로 초기화 메서드를 호출할 필요가 없다.

Bean Scope

Bean의 생명주기, 즉 Bean이 생성되고, 존재하며, 파괴되는 범위 결정

@Service
@Scope("prototype")
public class MyPrototypeService {
    // ...
}
  • singleton (default)
    • 애플리케이션에서 Bean 등록시 singleton scope로 등록
    • Spring IoC 컨테이너 당 한 개의 인스턴스 생성
    • 컨테이너가 Bean 가져다 주입할 때 항상 같은 객체 사용
    • 메모리나 성능 최적화에 유리
  • prototype
    • 컨테이너에서 Bean 가져다 쓸 때 항상 다른 인스턴스 사용
    • 모든 요청에서 새로운 객체 생성
    • gc에 의해 Bean 제거
  • request
    • Bean 등록 시 하나의 HTTP request 생명주기 안에 단 하나의 Bean만 존재
    • 각각의 HTTP 요청은 고유 Bean 객체 보유
  • session
    • 하나의 HTTP Session 생명주기 안에 단 하나의 Bean만 존재
  • global session
    • 하나의 global HTTP Session 생명주기 안에 한 개의 Bean 지정
  • application
    • ServletContext 생명주기 안에 한 개의 Bean 지정
profile
야호

0개의 댓글