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


100

스프링 주입이 @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();       
}

답변:


133

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

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

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

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

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

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


이렇게 생성 된 빈을 덮어 쓸 수 있습니까? 예를 들어, 빈 생성 메서드를 직접 호출하는 Spring 정의 클래스가 있습니다. 내가 원하는 것은 그 메소드로 생성 된 빈이 사용되는 것이 아니라 내가 정의하는 것입니다 ( @Bean그리고 주석을 달아서 @Primary).
Fons

4
그러나 프록시 (jdk 또는 CGLIB 중 어느 쪽이든)가 자체 호출에서 작동하지 않는다는 것을 기억합니다. 그래서 @Configuration은 어떻게 빈 간 종속성을 정의합니까? 그것은 바로 자기 호출을 사용
Nowhy

3
@Nowhy CGLib allows us to create proxy classes at runtime by creating sub class of specified class using Byte code generation. CGLib proxies are used in the case where Proxy is to be created for those class which does not have any interfaces or have methods which are not declared in the implementing interface. 이 경우 CGLIB는 @Configuration 클래스의 하위 클래스를 만들고 해당 메서드 (@Bean 메서드 포함)를 재정의합니다. 따라서 다른 메서드에서 @Bean 메서드를 호출 할 때 실제로 재정의 된 버전을 호출합니다 (Java 동적 바인딩 덕분에).
Flame239

그래서 @Componentjava Poxy 대신 CHLIB를 사용하여 프록시를 생성 하면 selfInvocation AOP 가 작동합니까?
Antoniossss
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.