인프런 커뮤니티 질문&답변

임형준님의 프로필 이미지

작성한 질문수

스프링 핵심 원리 - 기본편

static factory method로 빈 생성

해결된 질문

작성

·

114

·

수정됨

1

스프링으로 전환하기 1:07 부터의 강의 내용에 추가로 공부하다가 생긴 의문점에 관한 내용입니다.

스프링공식문서

위의 공식문서에서는 빈을 생성하는 또다른 방법으로 정적 팩터리 메서드가 있다고 했습니다.

public class StaticFactoryMethodBean {

    private String value;

    private StaticFactoryMethodBean(String value) {
        this.value = value;
    }

    public static StaticFactoryMethodBean createInstance(String value) {
        return new StaticFactoryMethodBean(value);
    }
}

이런 클래스가 있다고 가정하면, 두가지 종류의 빈을 만들 수 있습니다.

@Configuration
public class AppConfig {
    @Bean
    public StaticFactoryMethodBean factoryMethodBean() {
        return StaticFactoryMethodBean.createInstance("value");
    }

    @Bean
    public static StaticFactoryMethodBean staticFactoryMethodBean() {
        return StaticFactoryMethodBean.createInstance("value");
    }
}



여기서 생기는 궁금점이 있어서 질문드립니다.

이 static 빈은 @Configuration 에 영향을 받지 않고, 프록시를 생성하지 않아 여러 기능들을 쓸 수 없다고 생각이 들었습니다.

그럼에도 이걸 쓰는 경우가 있을까 해서 질문드립니다. 제 생각엔 외부 라이브러리나 이런거를 쓸 때, 쓸 거 같기도 하단 생각이 들었습니다. 혹시 실무에서도 쓰는 경우가 종종 있었는지 여쭈어봅니다.

p.s 실제 두개 다 생성이 되는지에 대한 검증 테스트 완료(간단하게 main테스트로 진행)

public class StaticFactoryMethodBeanMain { public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); StaticFactoryMethodBean factoryMethodBean = context.getBean("factoryMethodBean", StaticFactoryMethodBean.class); System.out.println(factoryMethodBean); StaticFactoryMethodBean staticFactoryMethodBean = context.getBean("staticFactoryMethodBean", StaticFactoryMethodBean.class); System.out.println(staticFactoryMethodBean); } }

답변 2

2

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. 임형준님

static을 사용하면 다른 빈들보다 더 빠르게 빈을 조기에 로딩할 수 있습니다.

참고로 이 방법은 일반적인 경우에는 사용하지 않습니다.

예를 들어서 빈 포스트 프로세서 같은 곳에서는 모든 빈을 체크해야 하는데, 그 전에 빈이 필요하다면 static을 사용해서 다른 빈 보다 빈을 초기에 등록할 수 있습니다.

이 부분은 빈 포스트 프로세서 같은 것을 공부해보시면 이해하는데 도움이 되실거에요.

빈 포스트 프로세서는 스프링 핵심원리 고급편에서 다룹니다.

감사합니다.

0

안녕하세요. 임형준님, 공식 서포터즈 David입니다.

답변 드리는데 필요한 정보를 요청드립니다:)

 

이 static 빈은 @Configuration 에 영향을 받지 않고, 프록시를 생성하지 않아

이 부분에 대해서 조금 더 자세히 설명 부탁드립니다.

  1. static 빈이 @Configuration에 영향을 받지 않는 이유

  2. (무엇에 대한) 프록시를 생성하지 않는 이유

 

제 생각엔 외부 라이브러리나 이런거를 쓸 때, 쓸 거 같기도 하단 생각이 들었습니다.

형준님께서 생각하신 외부 라이브러이에서의 사용 예시를 들어주실 수 있으실까요?

 

감사합니다.

임형준님의 프로필 이미지
임형준
질문자

<1, 2번에 대한 저의 설명>
https://docs.spring.io/spring-framework/reference/core/beans/java/basic-concepts.html

> When @Bean methods are declared within classes that are not annotated with @Configuration - or when @Configuration(proxyBeanMethods=false) is declared -, they are referred to as being processed in a "lite" mode. In such scenarios, @Bean methods are effectively a general-purpose factory method mechanism without special runtime processing (that is, without generating a CGLIB subclass for it).

@Bean 메서드가 @Configuration으로 애노테이션이 지정되지 않은 클래스 내부에서 선언되거나, @Configuration(proxyBeanMethods=false)가 선언된 경우, 이를 "라이트" 모드에서 처리된다. 이러한 시나리오에서 @Bean 메서드는 사실상 특별한 런타임 처리 없이 범용 목적의 팩토리 메서드 메커니즘으로 동작한다.

> As a consequence, @Bean methods on classes without runtime proxying are not meant to declare inter-bean dependencies at all. Instead, they are expected to operate on their containing component’s fields and, optionally, on arguments that a factory method may declare in order to receive autowired collaborators.

그 결과, 런타임 프록시가 없는 클래스의 @Bean 메서드는 빈 간의 의존성을 선언하기 위한 용도로 사용되지 않는다. 대신, 이러한 메서드는 해당 컴포넌트의 필드에 대해 동작하고, 선택적으로 팩토리 메서드가 자동 주입된 협력자를 받기 위해 선언할 수 있는 인자에 대해 동작하는 것으로 예상된다.


즉, @Configuration이 적용된 클래스는 스프링 컨테이너에 의해서 CGLIB 프록시로 감싸집니다. static 메서드는 인스턴스가 아니기 때문에 @Configuration의 적용을 받지 않습니다.

<외부 라이브러이에서의 사용 예시>
그냥 이 부분은 생각만 하고 검증한 것은 아니라 틀릴 수도 있습니다. 죄송합니다.
그냥 단순히 레디스 같은 외부라이브러리의 환경셋팅을 변경해서 적용하거나 할 때, 쓰일 수 있을거 같다는 저의 생각이었습니다.