스프링 : @Component 대 @Bean


459

@Component클래스 패스 스캐닝을 사용하여 xml bean 정의를 제거하기 위해 주석이 스프링 2.5에 도입 되었다는 것을 이해합니다 .

@Bean는 스프링 3.0에서 도입되었으며 @Configurationxml 파일을 완전히 제거하고 대신 java config를 사용하기 위해 사용할 수 있습니다 .

@Component주석을 도입하는 대신 주석 을 재사용 할 수 @Bean있었습니까? 내 이해는 최종 목표가 두 경우 모두에서 콩을 만드는 것입니다.


4
@Bean을 Configuration 클래스와 별도로 사용할 수있는 곳이 있습니까?
Willa


@Willa 예, 있습니다. 이라고 Lite mode합니다. 그리고 권장하지 않습니다. 여기를보십시오 : docs.spring.io/spring/docs/current/spring-framework-reference/…
smwikipedia

8
필자 @bean는 스프링 빈의 사용자 정의 가능한 인스턴스 를 반환 하는 메소드를 사용 하면서 @component나중에 필요할 때 스프링 IoC 엔진에 의해 정의 될 수있는 클래스를 정의 한다고 요약했습니다 .
Sebas

답변:


433

@Component그리고 @Bean두 개의 아주 다른 일을하고 혼동해서는 안됩니다.

@Component(및 @Service@Repository)는 클래스 경로 검색을 사용하여 Bean을 자동 감지하고 자동 구성하는 데 사용됩니다. 어노테이션이있는 클래스와 Bean (즉, 클래스 당 하나의 Bean) 사이에 암시 적 일대일 맵핑이 있습니다. 이 제어 방식은 순전히 선언적이므로 배선 제어가 상당히 제한됩니다.

@Bean위와 같이 Spring이 자동으로 수행하도록하는 대신 단일 Bean 을 명시 적으로 선언하는 데 사용됩니다 . 클래스 정의에서 Bean 선언을 분리하고 원하는 방식으로 Bean을 작성하고 구성 할 수 있습니다.

질문에 대답하려면 ...

@Component주석을 도입하는 대신 주석 을 재사용 할 수 있었 @Bean습니까?

아마; 그러나 그들은 서로 다르기 때문에 선택하지 않았습니다. 봄은 이미 물을 더럽 히지 않고 충분히 혼란 스럽습니다.


3
그래서 자동 @Component유선이 필요할 때만 사용할 수 있습니까? @Bean영향을 줄 수없는 것 같습니다@Autowired
Jaskey

3
서비스 기반 클래스에는 '@component'를 사용하고, 공장은보다 맞춤화 된 객체로 '@Bean'을 사용합니다 (예 : jdbc 데이터 소스
Junchen Liu

2
당신이 사용할 수있는 @Jaskey @Autowired@Bean당신이 당신의 bean 클래스를 주석 한 경우@Configuration
starcorn

6
죄송하지만 설명의 단어를 이해할 수 없습니다. 당신은 이것을 분명히 이해하고 있으므로 명확한 설명을 쓰거나 적절한 문서를 가리켜 주시겠습니까?
Alex Worden

13
이제 다른 사람들의 답변을 읽음으로써 개념을 이해 했으므로 설명이 의미가 있습니다. 당신의 설명이 이미 개념을 이해하지 못하는 사람에게는 좋지 않다는 것을 말해줍니다.
Alex Worden

397

@Component 구성 요소 스캔 및 자동 배선에 적합합니다.

언제 @Bean 을 사용해야 합니까?

때로는 자동 구성이 옵션이 아닙니다. 언제? 타사 라이브러리의 구성 요소를 연결하려고한다고 가정합니다 (소스 코드가 없으므로 클래스에 @Component로 주석을 달 수 없으므로) 자동 구성이 불가능합니다.

@Bean 어노테이션은 객체 반환 스프링 애플리케이션 컨텍스트 내에서 빈으로 등록해야합니다. 방법의 몸은 인스턴스를 생성을 담당하는 로직을 맺는다.


5
나는 이것이 가장 의미가 있다고 생각합니다. 내가 올바르게 이해하면 @Component클래스 자체 @Bean가 진행되는 동안 클래스 메서드가 진행됩니다 (클래스 객체의 인스턴스를 생성 함).
jocull

182

동적 상태에 따라 특정 구현을 원한다고 가정 해 봅시다. @Bean이 경우에 완벽합니다.

@Bean
@Scope("prototype")
public SomeService someService() {
    switch (state) {
    case 1:
        return new Impl1();
    case 2:
        return new Impl2();
    case 3:
        return new Impl3();
    default:
        return new Impl();
    }
}

그러나와 함께 할 수있는 방법은 없습니다 @Component.


3
이 예제 클래스를 어떻게 부릅니까?
PowerFlower

1
@PowerFlower이 메소드는 다음과 같이 주석이 달린 구성 클래스에 있어야합니다.@Configuration
Juh_

98
  1. @Component auto는 classpath 스캐닝을 사용하여 bean을 감지 하고 구성하는 반면 @Bean Spring이 자동으로 수행하지 않고 단일 bean을 명시 적으로 선언 합니다.
  2. @Component 클래스 정의에서 Bean 선언을 분리 합니다. @Bean은 Bean 정의를 클래스 정의에서 분리 합니다.
  3. @Component는 클래스 레벨 주석 인 반면 @Bean은 메소드 레벨 주석 이며 메소드 이름은 Bean 이름으로 사용됩니다.
  4. @Component 어노테이션 은 @Configuration 주석 이 달린 클래스 내에서 사용해야 하는 @Configuration 어노테이션 과 함께 사용될 필요는 없습니다 .
  5. 우리는 빈 만들 수 없습니다 클래스는 우리가 반면 외부 스프링 컨테이너의 경우, @Component를 사용하여 클래스를 빈 만들 수 클래스가 존재하는 경우 @Bean도를 사용하여 클래스를 외부 스프링 컨테이너가 .
  6. @Component에는 @Controller, @Repository 및 @Service와 같은 다른 특수화 가 있지만 @Bean에는 특수화없습니다 .

3
4. 실제로 @Bean은 비 구성 클래스에서 선언 될 수 있습니다. 라이트 모드로 알려진
voipp

1
포인트 5에 관해서는 스프링 컨테이너 안에 콩을 넣은 것 같습니다. 따라서 모든 클래스는 스프링 컨테이너 외부에 있습니다. 포인트 5는 보상되어야합니다
유겐

97

두 접근법 모두 Spring 컨테이너에 대상 유형을 등록하는 것을 목표로합니다.

차이점은 메소드 에는 적용 가능 하지만 유형 에는 적용 @Bean가능 하다는 것 입니다 .@Component

따라서 @Bean주석 을 사용할 때 메소드 본문에서 인스턴스 작성 로직을 제어합니다 ( 위 예제 참조 ). 로 다음 @Component주석 당신은 할 수 없습니다.


유형은 무엇입니까?
Jac Frall

20

나는 많은 대답을 보았고 거의 모든 곳에서 언급 된 @Component는 컴포넌트가 스캔되는 곳의 autowiring을위한 것이고 @Bean은 그 bean이 다르게 사용될 것이라고 정확하게 선언하고있다. 어떻게 다른지 보여 드리겠습니다.

  • @콩

먼저 메소드 레벨 주석입니다. 두 번째로 일반적으로 Java 코드에서 Bean을 구성하고 (xml 구성을 사용하지 않는 경우) ApplicationContext의 getBean 메소드를 사용하여 클래스에서 Bean을 호출하는 데 사용합니다. 처럼

 @Configuration
class MyConfiguration{
    @Bean
    public User getUser(){
        return new User();
    }
}

class User{
}



//Getting Bean 
User user = applicationContext.getBean("getUser");
  • @구성 요소

특수 bean이 아닌 bean에 주석을 달기위한 일반적인 방법입니다. 클래스 레벨 주석이며 Java 또는 xml 구성을 통해 모든 구성 요소를 피하는 데 사용됩니다.

우리는 이와 같은 것을 얻습니다.

@Component
class User {
}

//to get Bean
@Autowired
User user;

그게 다야. 해당 Bean을 인스턴스화하고 사용하기위한 모든 구성 단계를 피하기 위해 방금 소개되었습니다.


5
@Bean접근 방식 을 사용할 때 ApplicationContext에서 User 객체를 가져올 필요가 없다고 생각합니다 . 의 @Autowire경우처럼 빈을 얻는 데 여전히 사용할 수 있습니다 @Component. @Bean그냥 스프링 컨테이너에 Bean을 추가합니다 @Component. 차이점은 다음과 같습니다. 1.을 사용하여 @Bean써드 파티 클래스를 스프링 컨테이너에 추가 할 수 있습니다. 2.를 사용하면 @Bean런타임에 원하는 인터페이스 구현을 얻을 수 있습니다 (공장 디자인 패턴 사용)
Andy

20

@BeanSpring 프레임 워크 애플리케이션 컨텍스트에서 기존 써드 파티 클래스를 사용 가능하게하는 데 사용할 수 있습니다 .

@Bean
public ViewResolver viewResolver() {

    InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();

    viewResolver.setPrefix("/WEB-INF/view/");
    viewResolver.setSuffix(".jsp");

    return viewResolver;
}

@Bean주석 을 사용하면 써드 파티 클래스 ( @Component스프링이 없을 수도 있고 사용하지 않을 수도 있음)를 스프링 Bean으로 랩핑 할 수 있습니다 . 그런 다음을 사용하여 @Bean감싸면 단일 객체로 사용되며 Spring 프레임 워크 응용 프로그램 컨텍스트에서 사용할 수 있습니다. 종속성 주입 및을 사용하여 앱에서이 Bean을 쉽게 공유 / 재사용 할 수 있습니다 @Autowired.

@Bean주석은 타사 클래스의 래퍼 / 어댑터 라고 생각하십시오 . Spring 프레임 워크 애플리케이션 컨텍스트에서 써드 파티 클래스를 사용 가능하게하려고합니다.

@Bean위의 코드에서 사용 하면 메소드 내부에서 new키워드를 사용하여 명시 적으로 객체를 작성하기 때문에 단일 Bean을 명시 적으로 선언 합니다. 또한 주어진 클래스의 setter 메소드를 수동으로 호출합니다. 그래서 접두사 필드의 값을 변경할 수 있습니다. 따라서이 수동 작업을 명시 적 작성이라고합니다. @Component동일한 클래스에 대해를 사용하면 Spring 컨테이너에 등록 된 Bean은 접두사 필드의 기본값을 갖습니다.

반면에로 클래스에 주석을 달 때 키워드 @Component를 수동으로 사용할 필요가 없습니다 new. Spring이 자동으로 처리합니다.


1
이 답변은 그 콩이 잘 사용하는 방법의 예를 업데이트 한 경우 좋겠지
softarn

소스 코드가 수정을 허용하지 않는 경우 @Bean을 써드 파티 클래스로 어떻게 랩핑합니까?
veritas

16

@Component태그 를 사용하는 경우 , 바닐라 빈 선언 메소드 ()로 POJO (Plain Old Java Object)를 갖는 것과 동일 @Bean합니다. 예를 들어, 다음 방법 1과 2는 동일한 결과를 제공합니다.

방법 1

@Component
public class SomeClass {

    private int number;

    public SomeClass(Integer theNumber){
        this.number = theNumber.intValue();
    }

    public int getNumber(){
        return this.number;
    }
}

'theNumber'에 대한 빈과 함께 :

@Bean
Integer theNumber(){
    return new Integer(3456);
}

방법 2

//Note: no @Component tag
public class SomeClass {

    private int number;

    public SomeClass(Integer theNumber){
        this.number = theNumber.intValue();
    }

    public int getNumber(){
        return this.number;
    }
}

둘 다 콩과 함께 :

@Bean
Integer theNumber(){
    return new Integer(3456);
}

@Bean
SomeClass someClass(Integer theNumber){
    return new SomeClass(theNumber);
}

방법 2를 사용하면 Bean 선언을 함께 유지할 수 있으며 약간 더 유연합니다. 다음과 같이 Vanilla 이외의 SomeClass Bean을 추가 할 수도 있습니다.

@Bean
SomeClass strawberryClass(){
    return new SomeClass(new Integer(1));
}

10

Bean을 생성하는 두 가지 방법이 있습니다. 하나는 주석이있는 클래스를 만드는 것 @Component입니다. 다른 하나는 메소드를 작성하고 주석을 추가하는 것입니다 @Bean. with 메소드가 포함 된 클래스에 @Bean대해 주석을 달어야합니다. @Configuration 일단 스프링 프로젝트를 실행하면 @ComponentScan주석이 있는 클래스가 모든 클래스를 스캔 @Component하고이 클래스의 인스턴스를 Ioc 컨테이너로 복원합니다. 또 다른 @ComponentScan방법은 메소드를 실행 @Bean하고 Ioc 컨테이너에 Bean으로 리턴 오브젝트를 복원하는 것입니다. 따라서 현재 상태에 따라 어떤 종류의 Bean을 작성해야하는지 결정해야하는 경우@Bean. 논리를 작성하고 원하는 객체를 반환 할 수 있습니다. 언급 할 가치가있는 또 다른 것은 메소드의 이름은 @Bean기본 이름 인 bean입니다.


6
  • @component와 그 전문화 (@Controller, @service, @repository)는 클래스 경로 스캐닝을 사용하여 자동 감지를 허용합니다. @Controller, @service, @repository와 같은 컴포넌트 클래스가 컴포넌트 스캔을 사용하여 스프링 프레임 워크에 의해 자동으로 스캔됩니다.
  • 반면 @Bean은 구성 클래스에서 단일 Bean을 명시 적으로 선언하는 데만 사용할 수 있습니다.
  • @Bean은 스프링이 자동으로 수행하지 않고 단일 Bean을 명시 적으로 선언하는 데 사용됩니다. 클래스 정의에서 bean을 septate 선언합니다.
  • 간단히 말해 @Controller, @service, @repository는 자동 감지 및 @Bean으로 클래스에서 seprate bean을 만듭니다.
    -@ 컨트롤러
    공개 클래스 LoginController 
    {--code--}

    -@ 구성
    공개 클래스 AppConfig {
    @콩
    공개 SessionFactory sessionFactory () 
    {-코드-}

3

@Bean은 컴파일 타임에 Spring과 비즈니스 규칙을 연결하지 않도록 만들어졌습니다. 즉, PlayFramework 또는 JEE와 같은 다른 프레임 워크에서 비즈니스 규칙을 재사용 할 수 있습니다.

또한 기본 Spring 인스턴스화가 충분하지 않은 Bean 작성 방법을 완전히 제어 할 수 있습니다.

나는 그것에 대해 이야기하는 글을 썼습니다.

https://coderstower.com/2019/04/23/factory-methods-decoupling-ioc-container-abstraction/



1

1. @Component 정보 @Component
는 @Configuration과 유사하게 기능합니다.

둘 다 주석이 달린 클래스에 하나 이상의 Bean을 등록해야 함을 나타냅니다 Spring-IOC-Container.

@Component로 주석이 달린 클래스를 호출합니다 Component of Spring. 여러 개의 콩을 포함하는 개념입니다.

Component class의 빈을 등록하려면 Spring이 자동 스캔해야합니다 component class.

@Bean에 대하여 @Bean
component-class(위에서 언급 한) 메소드에 주석을 달기 위해 사용된다 . 주석이 달린 메소드에 의해 retured 된 인스턴스가에 등록되어야 함을 나타냅니다 Spring-IOC-Container.

3. 결론
둘 사이의 차이점은 비교적 분명하지 않으며,에 사용됩니다 different circumstances. 일반적인 사용법은 다음과 같습니다.

    // @Configuration is implemented by @Component
    @Configuration
    public ComponentClass {

      @Bean
      public FirstBean FirstBeanMethod() {
        return new FirstBean();
      }

      @Bean
      public SecondBean SecondBeanMethod() {
        return new SecondBean();
      }
    }

0

위의 답변에서 추가 포인트

여러 앱에서 공유되고 몇 가지 서비스가 포함 된 모듈이 있다고 가정 해 봅시다. 각 앱에 모두 필요한 것은 아닙니다.

해당 서비스 클래스에서 @Component를 사용하고 애플리케이션에서 컴포넌트 스캔을 사용하는 경우,

필요한 것보다 더 많은 콩을 감지하게 될 수도 있습니다

이 경우 구성 요소 스캔의 필터링을 조정하거나 사용하지 않은 Bean도 실행할 수있는 구성을 제공해야합니다. 그렇지 않으면 응용 프로그램 컨텍스트가 시작되지 않습니다.

이 경우 @Bean 주석으로 작업하고 해당 Bean을 인스턴스화하는 것이 좋습니다.

각 앱마다 개별적으로 필요합니다

따라서 기본적으로 @Bean을 사용하여 컨텍스트에 써드 파티 클래스를 추가하십시오. 그리고 @Component가 단일 응용 프로그램 안에있는 경우.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.