1.12.1 기본 개념: @Bean 및 @Configuration by sh

1.12. Java-based Container Configuration

이 섹션에서는 자바 코드에 어노테이션을 사용하여 스프링 컨테이너를 구성하는 방법을 설명합니다. 여기에는 다음 주제가 포함됩니다:

1.12.1. Basic Concepts: @Bean and @Configuration

스프링의 새로운 자바 구성 지원의 중심은 @Configuration-annotated 클래스와 @Bean-annotated 메소드입니다.

@Bean 어노테이션은 메소드가 스프링 IoC 컨테이너에 의해 관리될 새로운 객체를 인스턴스화, 구성 및 초기화하는 것을 나타내는 데 사용됩니다. 스프링의 <beans/>XML 구성에 익숙한 사람들을 위해 @Bean어노테이션은 <beans/>요소와 동일한 역할을 합니다. @Component어노테이션과 함께 @Bean-annotated 메소드를 사용할 수 있습니다. 그러나, @Configuration 빈과 함께 더 자주 사용됩니다.

@Configuration을 사용하여 클래스를 어노테이팅하는 것은 이것의 주된 목적이 빈 정의의 소스라는 것을 의미합니다. 게다가, @Configuration 클래스들은 같은 클래스에서 다른 @Bean 메소드들을 호출하여 빈 간의 의존성을 정의할 수 있도록 합니다. 가장 단순한 @Configuration 클래스는 다음과 같이 읽습니다:

@Configuration
public class AppConfig {

    @Bean
    public MyService myService() {
        return new MyServiceImpl();
    }
}

앞의 AppConfig클래스는 다음의 스프링 <beans/> XML과 동일합니다:

<beans>
    <bean id="myService" class="com.acme.services.MyServiceImpl"/>
</beans>

XML 대신 JavaConfig 사용

  • @Configuration 을 클래스에 적용하고 @Bean을 해당 클래스의 메소드에 적용하면 @Autowired로 빈을 부를 수 있다.

    • @Configuration: 빈 팩토리를 위한 오브젝트 설정을 담당하는 클래스.

    • @Bean: 오브젝트를 만들어 주는 메소드

  • 어떤 클래스를 빈으로 만들기 위해서는 @Bean을 사용하거나, @Component를 사용하면 된다. 사용하는 관점에서의 차이가 존재한다.

    • @Component: 스프링에서 자동으로 찾고 관리해주는 빈. 클래스의 상단에 작성. 클래스 이름이 빈 이름이 됨(default).

    • @Bean: @Configuration으로 선언된 클래스 내에 있는 메소드를 정의할 때 사용. 이 메소드가 반환하는 객체가 빈이 됨. 메소드 이름이 빈 이름이 됨(default).

Full @Configuration vs “lite” @Bean mode?

@Bean 메소드가 @Configuration으로 어노테이팅되지 않은 클래스 내에서 선언되면, 그 메소드들은 “lite” 모드로 처리되는 것으로 간주됩니다. @Component또는 평범한 구식 클래스에서 선언된 빈 메소드들은 “lite”로 간주되며, 이는 포함하는 클래스의 기본 목적이 다르며 @Bean 메소드는 보너스의 한 종류가 됩니다. 예를 들어, 서비스 구성요소는 적용 가능한 각 구성 요소 클래스의 추가 @Bean 메소드를 통해 관리 뷰를 컨테이너에 노출시킬 수 있습니다. 이러한 시나리오에서 @Bean메소드들은 범용 팩토리 메소드 메커니즘입니다.

Full @Configuration과 달리 “lite” @Bean메소드는 빈 간의 의존성을 선언할 수 없습니다. 대신, 포함하는 구성요소의 내부 상태와 선택적으로 선언할 수 있는 인수에 따라 작동합니다. 따라서, 이러한 @Bean메소드는 다른 @Bean 메소드를 호출하지 않아야 합니다. 이러한 각각의 메소드는 특별한 런타임 시맨틱 없이 문자 그대로 특정 빈 참조에 대한 팩토리 메소드입니다. 여기서 긍정적인 부작용은 런타임에 CGLIB 서브 클래 싱을 적용할 필요가 없으므로 클래스 디자인 측면에서 제한이 없다는 것입니다. (즉, 포함된 클래스가 final클래스가 될 수 있습니다.

일반적인 시나리오에서 @Bean 메소드는 @Configuration 클래스 내에서 선언되어야 하므로, “전체” 모드가 항상 사용되며 교차 메소드 참조가 컨테이너의 수명 주기 관리로 리디렉션 됩니다. 이렇게 하면 동일한 @Bean 메소드가 실수로 자바 호출을 통해 호출되는 것을 방지할 수 있으므로 “lite” 모드에서 작동할 때 추적하기 어려운 미묘한 버그를 줄일 수 있습니다.

@Bean@Configuration어노테이션은 다음 섹션에서 자세히 설명합니다. 그러나, 먼저 자바 기반 구성을 사용하여 스프링 컨테이너를 만드는 다양한 방법을 다룹니다.

스프링 빈의 “lite(가벼운?)” 모드

  • 해당 설정에 @Configuration 어노테이션이 아닌 @Component 어노테이션을 작성하면 그것이 lite 모드가 된다. 큰 차이는 Cglib 사용 유무이다.

    • @Configuration의 경우에는 cglib를 사용함.

    • @Component의 경우에는 cglib를 사용하지 않음.

Ex. NothingBean이 SomeBean의 의존성을 주입 받고 있는 상황.

  • someBean의 메소드 호출 횟수에 차이가 있음. 일반적으로 볼 때는 두 번 호출 예상. (SomeBean을 빈으로 등록할 때 1번 + NothingBean을 빈으로 등록할 때 someBean() 메소드를 호출 1번)

    • @Configuration -> cglib를 사용해서 위의 someBean을 한 번만 호출하게 함.

    • @Component -> cglib를 사용하지 않으므로 someBean을 두 번 호출.

      • @Configuration은 cglib를 사용해서 일반적으로 @Component를 사용할 때 보다 느리지만, 그 차이가 눈에 띄지는 않음.

       lite 모드가 스프링을 사용하는 데에 아주 쓸모 있는 기능은 아니므로 그냥 Configuration 사용 권장!

Last updated