[java] Spring Java 구성에서 @Bean 주석이 달린 메소드 호출

스프링 주입이 @Bean주석을 사용하여 호출 메서드를 처리하는 방법에 대해 궁금합니다 . @Bean메서드에 주석을 달고 인스턴스를 반환하면 스프링이 메서드를 호출하고 반환 된 인스턴스를 가져 와서 빈을 만들도록 지시한다는 것을 이해합니다. 그러나 때로는 해당 빈을 사용하여 다른 빈을 연결하거나 다른 코드를 설정해야합니다. 이 작업을 수행하는 일반적인 방법은 @Bean주석이있는 메서드를 호출하여 인스턴스를 가져 오는 것입니다. 제 질문은 왜 이것이 빈의 여러 인스턴스가 떠 다니는 원인이되지 않습니까?

예를 들어, 아래 코드를 참조하십시오 (다른 질문에서 발췌). 이 entryPoint()메서드는 주석이 달려 @Bean있으므로 spring이의 새 인스턴스를 BasicAuthenticationEntryPoint빈으로 생성한다고 상상할 수 있습니다 . 그런 다음 entryPoint()configure 블록에서 다시 호출 하지만 entryPoint()빈 인스턴스를 반환하는 것처럼 보이며 여러 번 호출되지 않습니다 (로깅을 시도했지만 로그 항목이 하나뿐입니다). 잠재적으로 entryPoint()구성의 다른 부분에서 여러 번 호출 할 수 있으며 항상 동일한 인스턴스를 얻을 수 있습니다. 이것에 대한 나의 이해가 맞습니까? Spring은 주석이 달린 메소드를 마법처럼 재 작성 @Bean합니까?

@Bean
public BasicAuthenticationEntryPoint entryPoint() {
    BasicAuthenticationEntryPoint basicAuthEntryPoint = new BasicAuthenticationEntryPoint();
    basicAuthEntryPoint.setRealmName("My Realm");
    return basicAuthEntryPoint;
}

@Override
protected void configure(HttpSecurity http) throws Exception {

    http
        .exceptionHandling()
            .authenticationEntryPoint(entryPoint())
            .and()
        .authorizeUrls()
            .anyRequest().authenticated()
            .and()
        .httpBasic();
}



답변

예, Spring은 약간의 마술을 합니다. Spring Docs 확인 :

이것이 마법이 들어오는 곳입니다. 모든 @Configuration클래스는 시작시 CGLIB 로 서브 클래 싱됩니다 . 하위 클래스에서 자식 메서드는 부모 메서드를 호출하고 새 인스턴스를 만들기 전에 먼저 컨테이너에서 캐시 된 (범위가 지정된) 빈이 있는지 확인합니다.

이것은 @Bean메소드에 대한 호출이 CGLIB 를 통해 프록시 되므로 캐시 된 버전의 Bean이 리턴 됨을 의미합니다 (새 버전이 작성되지 않음).

@Beans 의 기본 범위는 이며 SINGLETON, PROTOTYPE호출이 원래 메서드로 전달되는 것과 같이 다른 범위를 지정하면 입니다.

이것은 정적 메서드에는 유효하지 않습니다 . 봄 문서에 따르면 :

기술적 한계로 인해 (이 섹션의 앞부분에서 설명한대로) 클래스 @Bean내에서도 컨테이너 가 정적 메서드에 대한 호출을 가로 채지 않습니다 @Configuration. CGLIB 하위 클래스는 비 정적 메서드 만 재정의 할 수 있습니다. 결과적으로 다른 @Bean메서드에 대한 직접 호출 은 표준 Java 의미 체계를 가지므로 팩토리 메서드 자체에서 직접 독립 인스턴스가 반환됩니다.


답변