1.10.5 component 내에 Bean 메타 데이터 정의

스프링 컴포넌트는 컨테이너에 빈 정의 메타 데이터를 제공 할 수있다. @Configurationannotation이 달린 클래스 내에서 bean 메타 데이터를 정의하는 데 사용되는 것과 동일한 @Bean annotation 으로 이를 수행 할 수 있습니다 . 다음 예제에서는 이를 수행하는 방법을 보여줍니다.

@Component
public class FactoryMethodComponent {

    @Bean
    @Qualifier("public")
    public TestBean publicInstance() {
        return new TestBean("publicInstance");
    }

    public void doWork() {
        // Component method implementation omitted
    }
}

@Configuration@Bean 어노테이션만 있으면 간단하게 설정파일을 작성할 수 있다. @Bean

메소드레벨에서 사용된다. @Configuration 어노테이션과 같이 동작하고 스프링 빈을 만들어낸다. @Configuration이 디펜던시를 객체화시키고 설정하는 메소드를 가지게 되는데 이러한 메소드들은 @Bean으로 annotated된다. 이 @Bean으로 어노테이션된 메소드들은 bean ID와 함께 작동하며 실제 빈을 생성하고 리턴한다

앞의 클래스는 내부에 doWork()메소드가 있는 에 애플리케이션에 특화된 코드가 있는 Spring 컴포넌트이다 . 그러나 publicInstance()메소드를 참조하는 팩토리 메소드가있는 Bean 정의도 제공합니다. @Beanannotation 은 팩토리 메소드 와 @Qualifierannotation 을 통한 제한자의 값 같은 다른 빈정의 프로퍼티들을 식별한다. 지정 될 수있는 다른 메서드 레벨의 annotation 은 @Scope, @Lazy및 사용자 지정 한정자 annotation으로 얘기할 수 있다.

구성 요소 초기화에 대한 역할 외에도 @Autowired 또는 @Inject로 표시된 주입 지점에 @Lazy 주석을 배치 할 수도 있습니다. 이러한 맥락에서, 이것은 지연 해상도 프록시 (lazy-resolution proxy)의 주입으로 이어진다.

앞에서 설명한 것처럼 autowired 필드와 메소드는 @Bean메소드의 autowiring에 대한 추가 지원과 함께 지원됩니다 . 다음 예제에서는 이를 수행하는 방법을 보여줍니다.

@Component
public class FactoryMethodComponent {

    private static int i;

    @Bean
    @Qualifier("public")
    public TestBean publicInstance() {
        return new TestBean("publicInstance");
    }

    // 커스텀 qualifier와 메서드 파라미터의 자동연결의 사용
    @Bean
    protected TestBean protectedInstance(
            @Qualifier("public") TestBean spouse,
            @Value("#{privateInstance.age}") String country) {
        TestBean tb = new TestBean("protectedInstance", 1);
        tb.setSpouse(spouse);
        tb.setCountry(country);
        return tb;
    }

    @Bean
    private TestBean privateInstance() {
        return new TestBean("privateInstance", i++);
    }

    @Bean
    @RequestScope
    public TestBean requestScopedInstance() {
        return new TestBean("requestScopedInstance", 3);
    }
}

이 예제는 String메소드 매개 변수 country를 다른 bean privateInstanceage특성 값으로 자동 작성합니다 . Spring 표현식 언어 요소는 #{ <expression> }표기법을 통해 특성 값을 정의합니다. 대한 @Value annotation에 대한 표현의 해결은 표현의 텍스트를 해석 할 때 빈 이름을 찾아 미리 구성되어 있습니다.

Spring Framework 4.3에서, 현재 bean의 생성을 트리거하는 요청하는 주입 지점에 접근하기 위해 factory 메소드 매개 변수를 type InjectionPoint(또는보다 구체적인 하위 클래스 :DependencyDescriptor)로 선언 할 수도 있습니다 . 이것은 기존 인스턴스를 삽입하는 것이 아니라 실제 빈 인스턴스를 만드는 경우에만 적용된다는 점에 유의하십시오. 따라서 이 기능은 프로토 타입 범위의 빈에 가장 적합합니다. 다른 스코프의 경우, 팩토리 메소드는 주어진 스코프 (예를 들어, lazy singleton bean의 생성을 트리거 한 종속성)에서 새로운 빈 인스턴스를 생성하도록 유발 한 주입 지점만을 볼 수있다. 이러한 시나리오에서 제공된 주입 지점 메타 데이터를 의미 체계 관리와 함께 사용할 수 있습니다. 다음 예제에서는 InjectionPoint사용 방법을 보여줍니다.

@Component
public class FactoryMethodComponent {

    @Bean @Scope("prototype")
    public TestBean prototypeInstance(InjectionPoint injectionPoint) {
        return new TestBean("prototypeInstance for " + injectionPoint.getMember());
    }
}

일반 Spring 구성 요소 의 @Bean메소드는 Spring @Configuration클래스 내부 의 메소드와 다르게 처리됩니다 . 차이점은 @Component 클래스가 메소드와 필드의 호출을 가로 채기 위해 CGLIB로 향상되지 않는다는 것입니다. CGLIB 프록 싱은 @Configuration클래스 @Bean메소드 내의 메소드 또는 필드를 호출하여 협업 객체에 대한 bean 메타 데이터 참조를 작성 하는 수단 입니다. 이러한 메소드는 일반적인 자바 의미와 함께 호출되지 않고 @Bean메소드에 대한 로그래밍 방식의 호출을 통해 다른 Bean을 참조 할 때에도 Spring Bean의 일반적인 수명주기 관리 및 프록시를 제공하기 위해 컨테이너를 거친다 . 대조적으로, @Component 클래스내의 @Bean메서드에서 메소드나 필드를 호출하는 방법 특수한 CGLIB 처리 나 다른 제약이 적용되지 않은 표준 자바 의미 가지고있다.

@Bean 메쏘드를 static으로 선언 할 수 있습니다. 인스턴스를 포함하는 설정 클래스를 생성하지 않고 호출 할 수 있습니다. 이는 BeanFactoryPostProcessor 또는 BeanPostProcessor 유형과 같은 포스트 프로세서 빈을 정의 할 때 특히 유용합니다. 이러한 빈은 컨테이너 수명주기 초기에 초기화되고 그 시점에서 구성의 다른 부분을 트리거하지 않아야하기 때문입니다.

정적 @Bean 메서드에 대한 호출은 컨테이너에 의해 절대로 가로 챌 수 없으며 기술 제한 사항으로 인해 @Configuration 클래스 (이 섹션의 앞 부분에서 설명 했음) 내에서도 인터셉트되지 않습니다. CGLIB 서브 클래 싱은 정적이 아닌 메서드 만 오버라이드 할 수 있습니다. 결과적으로 다른 @Bean 메소드에 대한 직접 호출은 표준 Java 의미론을 가지므로 독립 인스턴스가 팩토리 메소드 자체에서 바로 반환됩니다.

@Bean 메소드의 Java 언어 가시성은 Spring 컨테이너의 결과 빈 정의에 즉각적인 영향을 미치지 않습니다. 비 @Configuration 클래스와 정적 메서드에 적합하게 팩터 리 메서드를 자유롭게 선언 할 수 있습니다. 그러나 @Configuration 클래스의 일반 @Bean 메서드는 재정의 할 수 있어야합니다. 즉, private 또는 final로 선언하면 안됩니다.

@Bean 메소드는 주어진 컴포넌트 또는 구성 클래스의 기본 클래스뿐만 아니라 컴포넌트 또는 구성 클래스에 의해 구현 된 인터페이스에서 선언 된 Java 8 기본 메소드에서도 발견됩니다. 따라서 Spring 4.2에서 Java 8 기본 메소드를 통해 다중 상속도 가능하며 복잡한 구성을 작성하는 데 많은 유연성을 허용합니다.

마지막으로, 하나의 클래스는 같은 빈에 대해 여러 개의 @Bean 메소드를 가질 수있다. 런타임시 사용 가능한 의존성에 따라 사용할 여러 팩토리 메소드의 배열이다. 이것은 다른 구성 시나리오에서 "greediest"생성자 또는 팩토리 메소드를 선택하는 알고리즘과 동일합니다. 가장 많은 수의 종속성이있는 변형은 생성시 선택됩니다. 컨테이너가 여러 개의 @Autowired 생성자 사이에서 선택하는 것과 유사합니다.

Last updated