Primavera: @Component versus @Bean

459

Entendo que a @Componentanotação foi introduzida na primavera 2.5 para livrar-se da definição de bean xml usando a verificação do caminho de classe.

@Beanfoi introduzido na primavera 3.0 e pode ser usado com o @Configurationfim de se livrar completamente do arquivo xml e usar a configuração java.

Teria sido possível reutilizar a @Componentanotação em vez de introduzi-la @Bean? Meu entendimento é que o objetivo final é criar beans nos dois casos.

user1396576
fonte
4
Existe algum lugar em que o @Bean possa ser usado além da classe Configuration?
Willa
@ Willa Sim, existe. Isso é chamado Lite mode. E isso não é recomendado. Veja aqui: docs.spring.io/spring/docs/current/spring-framework-reference/…
smwikipedia
9
Eu resumiria dizendo que um método @beanretorna uma instância personalizável do spring bean, enquanto @componentdefine uma classe que pode ser instanciada posteriormente pelo mecanismo IoC da primavera, quando necessário.
Sebas

Respostas:

433

@Componente @Beanfaça duas coisas bem diferentes, e não deve ser confundida.

@Component(e @Servicee @Repository) são usados ​​para detectar e configurar automaticamente os beans usando a verificação do caminho de classe. Há um mapeamento implícito de um para um entre a classe anotada e o bean (ou seja, um bean por classe). O controle da fiação é bastante limitado com essa abordagem, pois é puramente declarativa.

@Beané usado para declarar explicitamente um único bean, em vez de permitir que o Spring faça isso automaticamente como acima. Ele separa a declaração do bean da definição de classe e permite criar e configurar os beans exatamente como você escolhe.

Para responder sua pergunta ...

teria sido possível reutilizar a @Componentanotação em vez de introduzi-la @Bean?

Claro, provavelmente; mas eles escolheram não, pois os dois são bem diferentes. A primavera já é confusa o suficiente sem atrapalhar ainda mais as águas.

skaffman
fonte
3
Então, eu só posso usar @Componentquando é necessário conectar automaticamente? Parece @Beanque não pode afetar@Autowired
Jaskey 18/11/2015
3
use '@Component' para as classes base de serviços, '@Bean' como a fábrica mais tailor-made objetos, por exemplo, jdbc fonte de dados
Junchen Liu
2
@Jaskey você pode usar @Autowiredcom @Beanque você tenha anotado a sua classe de bean com@Configuration
starcorn
6
Desculpe, mas não consigo entender uma palavra da sua explicação. Você entende isso claramente. Por favor, escreva uma explicação clara ou aponte para a documentação apropriada?
quer
13
Agora que entendi o conceito (lendo as respostas de outras pessoas), sua explicação faz sentido. O que me diz ainda mais que sua explicação não é boa para quem ainda não entende os conceitos.
quer
397

@ Componente Preferível para varredura de componentes e fiação automática.

Quando você deve usar o @Bean ?

Às vezes, a configuração automática não é uma opção. Quando? Vamos imaginar que você deseja conectar componentes de bibliotecas de terceiros (você não possui o código-fonte para não poder anotar suas classes com @Component), portanto, a configuração automática não é possível.

A anotação @Bean retorna um objeto que a primavera deve registrar como bean no contexto do aplicativo. O corpo do método possui a lógica responsável pela criação da instância.

MagGGG
fonte
5
Eu acho que isso faz mais sentido. Se eu entendi corretamente, @Componentcontinua as próprias classes enquanto @Beancontinua os métodos de classe (que produzem instâncias de objetos de classe).
21418 jocull
182

Vamos considerar que quero uma implementação específica, dependendo de algum estado dinâmico. @Beané perfeito para esse caso.

@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();
    }
}

No entanto, não há como fazer isso @Component.

outdev
fonte
3
Como você chama esse exemplo de classe?
PowerFlower
1
@PowerFlower Esse método deve estar em uma classe de configuração, anotada com@Configuration
Juh_ 13/09/19
98
  1. O @Component detecta e configura automaticamente os beans usando a verificação do caminho de classe, enquanto o @Bean declara explicitamente um único bean, em vez de permitir que o Spring faça isso automaticamente.
  2. @Component não dissociar a declaração do feijão a partir da definição de classe onde, como @Bean desacopla a declaração do feijão a partir da definição de classe.
  3. @Component é uma anotação em nível de classe, enquanto @Bean é uma anotação em nível de método e o nome do método serve como o nome do bean.
  4. O @Component não precisa ser usado com a anotação @Configuration, na qual a anotação @Bean deve ser usada na classe anotada com @Configuration .
  5. Não podemos criar um bean de uma classe usando @Component, se a classe estiver fora do contêiner de primavera, enquanto podemos criar um bean de uma classe usando o @Bean, mesmo que a classe esteja presente fora do contêiner de primavera .
  6. O @Component possui diferentes especializações, como @Controller, @Repository e @Service, enquanto o @Bean não possui especializações .
Saurabh Prakash
fonte
3
4. Na verdade, o @Bean pode ser declarado na classe de não configuração. É conhecido como modo lite
voipp
1
Em relação ao ponto 5. Acho que colocamos um feijão dentro do contêiner da primavera. Portanto, todas as aulas estão fora do contêiner de primavera. Eu acho que o ponto 5 deve ser recompensado
eugen 18/03
97

Ambas as abordagens visam registrar o tipo de destino no contêiner Spring.

A diferença é que @Beané aplicável aos métodos , enquanto que @Componenté aplicável aos tipos .

Portanto, ao usar a @Beananotação, você controla a lógica de criação da instância no corpo do método (veja o exemplo acima ). Com @Componentanotação, você não pode.

Nurlan Akashayev
fonte
O que é um tipo?
Jac Frall
20

Eu vejo muitas respostas e em quase todos os lugares o @Component mencionado é para ligação automática, onde o componente é verificado e o @Bean está exatamente declarando que o bean deve ser usado de maneira diferente. Deixe-me mostrar como é diferente.

  • @Feijão

Primeiro, é uma anotação no nível do método. Segundo, você geralmente usa para configurar beans em um código java (se você não estiver usando a configuração xml) e depois chamá-lo de uma classe usando o método getBean do ApplicationContext. gostar

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

class User{
}



//Getting Bean 
User user = applicationContext.getBean("getUser");
  • @Componente

É uma maneira geral de anotar um bean e não um bean especializado. Uma anotação em nível de classe e é usada para evitar todo esse material de configuração através da configuração java ou xml.

Temos algo parecido com isto.

@Component
class User {
}

//to get Bean
@Autowired
User user;

É isso aí . Foi introduzido apenas para evitar todas as etapas de configuração para instanciar e usar esse bean.

xpioneer
fonte
5
Eu acho que não é necessário obter o objeto de usuário do ApplicationContext quando você usa a @Beanabordagem. Você ainda pode usar @Autowirepara obter o bean como faria no caso de @Component. @Beanapenas adiciona o Bean ao contêiner de primavera da mesma forma que faria @Component. A diferença é a seguinte. 1. Usando @Bean, você pode adicionar Classes de Terceiros ao Spring Container. 2. Usando @Bean, você pode obter a implementação desejada de uma interface em tempo de execução (Usando o padrão de design de fábrica)
Andy
20

Você pode usar @Beanpara disponibilizar uma classe de terceiros existente para o contexto de aplicativo da estrutura Spring.

@Bean
public ViewResolver viewResolver() {

    InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();

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

    return viewResolver;
}

Usando a @Beananotação, você pode agrupar uma classe de terceiros (ela pode não ter @Componente não pode usar Spring), como um bean Spring. E, depois de empacotado @Bean, é como um objeto singleton e está disponível no seu contexto de aplicativo da estrutura Spring. Agora você pode compartilhar / reutilizar facilmente esse bean em seu aplicativo usando injeção e dependência @Autowired.

Então, pense na @Beananotação como um invólucro / adaptador para classes de terceiros. Você deseja disponibilizar as classes de terceiros para o contexto do aplicativo da estrutura Spring.

Usando @Beano código acima, declaro explicitamente um único bean porque, dentro do método, estou criando explicitamente o objeto usando a newpalavra - chave. Também estou chamando manualmente métodos setter da classe especificada. Para que eu possa alterar o valor do campo prefixo. Portanto, este trabalho manual é chamado de criação explícita. Se eu usar o @Componentpara a mesma classe, o bean registrado no contêiner Spring terá valor padrão para o campo prefixo.

Por outro lado, quando anotamos uma classe com @Component, não precisamos usar manualmente a newpalavra - chave. É tratado automaticamente pelo Spring.

elvis
fonte
1
Seria bom se essa resposta fosse atualizada com um exemplo de como esse bean também é usado
softarn 13/01
Como você agruparia um @Bean em uma classe de terceiros se o código-fonte não permitir modificações?
veritas
16

Quando você usa a @Componenttag, é o mesmo que ter um POJO (Plain Old Java Object) com um método de declaração de bean de baunilha (anotado com @Bean). Por exemplo, os seguintes métodos 1 e 2 fornecerão o mesmo resultado.

Método 1

@Component
public class SomeClass {

    private int number;

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

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

com um bean para 'theNumber':

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

Método 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;
    }
}

com o feijão para ambos:

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

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

O método 2 permite que você mantenha as declarações de bean juntas, é um pouco mais flexível etc. Você pode até querer adicionar outro bean SomeClass não baunilha, como o seguinte:

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

Você tem duas maneiras de gerar beans. Uma é criar uma classe com uma anotação @Component. O outro é criar um método e anotá-lo @Bean. Para as classes que contêm o método with, @Beandevem ser anotadas com @Configuration Depois que você executa o projeto da primavera, a classe com uma @ComponentScananotação varre todas as classes @Componentnele e restaura a instância dessa classe no Container Ioc. Outra coisa @ComponentScanque você faria é executar os métodos @Beannele e restaurar o objeto de retorno para o Ioc Container como um bean. Portanto, quando você precisar decidir que tipo de beans você deseja criar, dependendo dos estados atuais, precisará usar@Bean. Você pode escrever a lógica e retornar o objeto que deseja. Outra coisa que vale a pena mencionar é o nome do método com @Beano nome padrão de bean.

Dai Niu
fonte
6
  • O @component e suas especializações (@Controller, @service, @repository) permitem a detecção automática usando a verificação do caminho de classe. Se virmos a classe de componentes como @Controller, @service, @repository será verificada automaticamente pela estrutura spring usando a verificação de componentes.
  • O @Bean, por outro lado, só pode ser usado para declarar explicitamente um único bean em uma classe de configuração.
  • O @Bean costumava declarar explicitamente um único bean, em vez de permitir que a primavera o faça automaticamente. Faz a declaração separada do bean a partir da definição de classe.
  • Resumindo, @Controller, @service, @repository são para detecção automática e @Bean para criar bean separado da classe
    - @Controller
    classe pública LoginController 
    {--code--}

    - @Configuration
    classe pública AppConfig {
    @Feijão
    public SessionFactory sessionFactory () 
    {--code--}
alok
fonte
3

O @Bean foi criado para evitar o acoplamento do Spring e das regras de negócios em tempo de compilação. Isso significa que você pode reutilizar suas regras de negócios em outras estruturas, como PlayFramework ou JEE.

Além disso, você tem controle total sobre como criar beans, onde não é suficiente a instanciação padrão do Spring.

Eu escrevi um post falando sobre isso.

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

Daniel Andres Pelaez Lopez
fonte
3

Diferença entre Bean e Componente:

Diferença entre Bean e Componente

AzarEJ
fonte
1

1. Sobre o @Component
@Component funciona da mesma forma que o @Configuration.

Ambos indicam que a classe anotada possui um ou mais beans que precisam ser registrados Spring-IOC-Container.

A classe anotada por @Component, como chamamos Component of Spring. É um conceito que contém vários feijões.

Component classprecisa ser verificado automaticamente pelo Spring para registrar esses beans do component class.

2. Sobre o @Bean O
@Bean é usado para anotar o método de component-class(como mencionado acima). Indica que a instância recuperada pelo método anotado precisa ser registrada Spring-IOC-Container.

3. Conclusão
A diferença entre os dois é relativamente inconsciente, eles são usados ​​em different circumstances. O uso geral é:

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

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

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

Pontos adicionais das respostas acima

Digamos que temos um módulo que é compartilhado em vários aplicativos e contém alguns serviços. Nem todos são necessários para cada aplicativo.

Se usar @Component nessas classes de serviço e a varredura de componentes no aplicativo,

podemos acabar detectando mais feijões do que o necessário

Nesse caso, você teve que ajustar a filtragem da varredura de componente ou fornecer a configuração que até os beans não utilizados podem executar. Caso contrário, o contexto do aplicativo não será iniciado.

Nesse caso, é melhor trabalhar com a anotação @Bean e instanciar apenas esses beans,

exigidos individualmente em cada aplicativo

Portanto, essencialmente, use o @Bean para adicionar classes de terceiros ao contexto. E o @Component, se for apenas dentro do seu aplicativo único.

AzarEJ
fonte