BeanFactory vs ApplicationContext


235

Sou bastante novo no Spring Framework, ando brincando com ele e reunindo alguns aplicativos de amostra para avaliar o Spring MVC para uso em um projeto da empresa que está por vir. Até agora, eu realmente gosto do que vejo no Spring MVC, parece muito fácil de usar e incentiva você a escrever aulas que são muito amigáveis ​​ao teste de unidade.

Apenas como exercício, estou escrevendo um método principal para um dos meus projetos de amostra / teste. Uma coisa que não tenho certeza é sobre as diferenças exatas entre BeanFactoryeApplicationContext - qual é apropriado usar em quais condições?

Entendo que isso ApplicationContextse estende BeanFactory, mas se estou apenas escrevendo um método principal simples, preciso da funcionalidade extra que ApplicationContextfornece? E exatamente que tipo de funcionalidade extra fazApplicationContext fornece?

Além de responder "qual devo usar em um método main ()", existem padrões ou diretrizes quanto à implementação que devo usar nesse cenário? Meu método main () deve ser escrito para depender da configuração do bean / aplicativo no formato XML - isso é uma suposição segura ou estou bloqueando o usuário em algo específico?

E essa resposta muda em um ambiente da Web - se alguma de minhas turmas precisou conhecer o Spring, é mais provável que elas precisem ApplicationContext ?

Obrigado por qualquer ajuda. Sei que muitas dessas perguntas provavelmente foram respondidas no manual de referência, mas estou tendo dificuldades para encontrar uma análise clara dessas duas interfaces e dos prós / contras de cada uma sem ler o manual com um pente fino.

Respostas:


209

Os documentos da primavera são ótimos nisso: 3.8.1. BeanFactory ou ApplicationContext? . Eles têm uma tabela com uma comparação, vou postar um trecho:

Fábrica de Feijão

  • Instanciação / fiação do bean

Contexto do Aplicativo

  • Instanciação / fiação do bean
  • Registro automático do BeanPostProcessor
  • Registro automático do BeanFactoryPostProcessor
  • Acesso conveniente ao MessageSource (para i18n)
  • Publicação de ApplicationEvent

Portanto, se você precisar de algum dos pontos apresentados no lado do Contexto do Aplicativo, use ApplicationContext.


3
O BeanFactory é leve, mas se você estiver usando o Spring "de verdade", também poderá usar o ApplicationContext: há muito pouco gasto adicional se você não usar seus recursos sofisticados, mas eles ainda estarão disponíveis para se / quando você os usar.
MetroidFan2002 29/10/08

2
O que significa quando você diz "registro automático do BeanPostPorcessor"? Isso significa que a classe não precisa implementar essa interface?
Abidi

2
ApplicationContext suporta AOP contra BeanFactory.
ininprsr

1
Com BeanFactorypodemos passar parâmetros construtores dinamicamente, mas com ApplicationContextnão podemos fazer isso.
Príncipe Sangrento

1
Uma observação importante da documentação vinculada do Spring: "As versões do Spring 2.0 e posterior fazem uso intenso do ponto de extensão BeanPostProcessor (para efetuar proxies e similares) e, se você estiver usando apenas um BeanFactory simples, uma boa quantidade de suporte, como transações e AOP não terá efeito (pelo menos não sem algumas etapas extras de sua parte). "
MarkMonteiro

52

A Spring fornece dois tipos de contêiner COI, um é XMLBeanFactorye outro é ApplicationContext.

+---------------------------------------+-----------------+--------------------------------+
|                                       | BeanFactory     |       ApplicationContext       |
+---------------------------------------+-----------------+--------------------------------+
| Annotation support                    | No              | Yes                            |
| BeanPostProcessor Registration        | Manual          | Automatic                      |
| implementation                        | XMLBeanFactory  | ClassPath/FileSystem/WebXmlApplicationContext|
| internationalization                  | No              | Yes                            |
| Enterprise services                   | No              | Yes                            |
| ApplicationEvent publication          | No              | Yes                            |
+---------------------------------------+-----------------+--------------------------------+

insira a descrição da imagem aqui

  • FileSystemXmlApplicationContext Feijão carregado pelo caminho completo.
  • ClassPathXmlApplicationContext Feijão carregado através do CLASSPATH
  • XMLWebApplicationContexte AnnotationConfigWebApplicationContextbeans carregados no contexto do aplicativo da web.
  • AnnotationConfigApplicationContext Carregando beans Spring a partir da configuração baseada em anotação.

exemplo:

ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeansConfiguration.class);
  • ApplicationContexté o contêiner inicializado por a ContextLoaderListenerou ContextLoaderServletdefinido em a web.xmle ContextLoaderPlugindefinido em struts-config.xml.

Nota : XmlBeanFactoryfoi descontinuado a partir da Primavera 3.1 a favor de DefaultListableBeanFactorye XmlBeanDefinitionReader.


2
sua AnnotationConfigApplicationContext não -AnnotationConfigWebApplicationContext- abaixo ClassPathXmlApplicationContext no diagrama
Akhil Jain

48

Para mim, a principal diferença de escolher BeanFactorysobre ApplicationContextparece ser que ApplicationContextirá pré-instanciar todos os feijões. Dos documentos da Primavera :

O Spring define propriedades e resolve dependências o mais tarde possível, quando o bean é realmente criado. Isso significa que um contêiner Spring carregado corretamente pode posteriormente gerar uma exceção quando você solicitar um objeto, se houver um problema ao criar esse objeto ou uma de suas dependências. Por exemplo, o bean lança uma exceção como resultado de uma propriedade ausente ou inválida. Essa visibilidade potencialmente atrasada de alguns problemas de configuração é o motivo pelo qual as implementações do ApplicationContext, por padrão, pré-instanciam beans singleton. À custa de algum tempo inicial e memória para criar esses beans antes que eles sejam realmente necessários, você descobre problemas de configuração quando o ApplicationContext é criado, e não posteriormente. Você ainda pode substituir esse comportamento padrão para que os beans singleton sejam inicializados com preguiça, em vez de serem pré-instanciados.

Diante disso, eu escolhi inicialmente o BeanFactoryuso em testes de integração / desempenho, pois não queria carregar o aplicativo inteiro para testar beans isolados. No entanto - e alguém me corrija se eu estiver errado - BeanFactorynão suporta classpathconfiguração XML. Então, BeanFactorye ApplicationContextcada um fornece um recurso crucial que eu queria, mas nenhum dos dois.

Pelo que sei, a observação na documentação sobre a substituição do comportamento da instanciação padrão ocorre na configuração e é por bean, portanto, não posso simplesmente definir o atributo "lazy-init" no arquivo XML ou estou travou a manutenção de uma versão para teste e outra para implantação.

O que acabei fazendo foi estender o ClassPathXmlApplicationContextcarregamento lento de beans para uso em testes como este:

public class LazyLoadingXmlApplicationContext extends ClassPathXmlApplicationContext {

    public LazyLoadingXmlApplicationContext(String[] configLocations) {
        super(configLocations);
    }

    /**
     * Upon loading bean definitions, force beans to be lazy-initialized.
     * @see org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions(org.springframework.beans.factory.xml.XmlBeanDefinitionReader)
     */

    @Override
    protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
        super.loadBeanDefinitions(reader);
        for (String name: reader.getBeanFactory().getBeanDefinitionNames()) {
            AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) reader.getBeanFactory().getBeanDefinition(name);
            beanDefinition.setLazyInit(true);
        }
    }

}

2
Eu diria que, se seus testes de unidade estão carregando seu contexto completo do Spring, eles não são "testes de unidade", mas testes de integração.
mate b

1
Bom ponto. No meu caso, eu realmente precisava carregar beans do contexto para testes de desempenho e integração e escrevi "testes de unidade" por hábito. Eu editei minha resposta de acordo.
Lyle

2
BeanFactory doesn't support classpath XML configuration.Eu acho que sim: stackoverflow.com/questions/5231371/…
Xtreme Biker

29

Para adicionar o que Miguel Ping respondeu, aqui está outra seção da documentação que responde a isso também:

Versão curta: use um ApplicationContext, a menos que você tenha um bom motivo para não fazer isso. Para aqueles que procuram um pouco mais de profundidade quanto ao 'mas por que' da recomendação acima, continue lendo.

(publicando isso para futuros novatos da Primavera que possam ler esta pergunta)


19
  1. ApplicationContext é a maneira mais preferida do que BeanFactory

  2. Nas novas versões do Spring BeanFactoryé substituído por ApplicationContext. Mas ainda BeanFactoryexiste para compatibilidade com versões anteriores

  3. ApplicationContext extends BeanFactory e tem os seguintes benefícios
    • suporta internacionalização para mensagens de texto
    • suporta publicação de eventos para os ouvintes registrados
    • acesso a recursos como URLs e arquivos

13

ApplicationContext: ele carrega os spring beans configurados no arquivo de configuração da primavera e gerencia o ciclo de vida do spring beans como e QUANDO O RECIPIENTE COMEÇA. Não esperará até que getBean ("springbeanref") seja chamado.

BeanFactory Carrega beans de primavera configurados no arquivo de configuração de primavera, gerencia o ciclo de vida do bean de primavera quando chamamos getBean ("springbeanref") . Então, quando chamamos de getBean ("springbeanref") no momento do início do ciclo de vida do bean de primavera .


12

Eu acho que é melhor sempre usar o ApplicationContext, a menos que você esteja em um ambiente móvel, como alguém já disse. O ApplicationContext possui mais funcionalidades e você definitivamente deseja usar os PostProcessors, como RequiredAnnotationBeanPostProcessor, AutowiredAnnotationBeanPostProcessor e CommonAnnotationBeanPostProcessor, que ajudarão você a simplificar seus arquivos de configuração do Spring, além de poder usar anotações como @Required, @PostConstruct, @Resource, etc. .

Mesmo que você não use tudo o que o ApplicationContext oferece, é melhor usá-lo de qualquer maneira e, posteriormente, se você decidir usar alguns recursos, como mensagens ou pós-processadores ou outro esquema para adicionar avisos transacionais, já terá um ApplicationContext e não precisará alterar nenhum código.

Se você estiver escrevendo um aplicativo independente, carregue o ApplicationContext no seu método principal, usando um ClassPathXmlApplicationContext, obtenha o bean principal e chame run () (ou qualquer outro método) para iniciar o aplicativo. Se você estiver escrevendo um aplicativo Web, use o ContextLoaderListener em web.xml para que ele crie o ApplicationContext e você possa obtê-lo posteriormente no ServletContext, independentemente de estar usando JSP, JSF, JSTL, struts, Tapeçaria etc. .

Além disso, lembre-se de que você pode usar vários arquivos de configuração do Spring e criar o ApplicationContext listando todos os arquivos no construtor (ou listando-os no context-param para o ContextLoaderListener), ou você pode simplesmente carregar um arquivo de configuração principal que possui instruções de importação. Você pode importar um arquivo de configuração do Spring para outro arquivo de configuração do Spring usando <import resource = "otherfile.xml" />, que é muito útil quando você cria programaticamente o ApplicationContext no método principal e carrega apenas um arquivo de configuração do Spring.


6

Na maioria das vezes, o ApplicationContext é preferido, a menos que você precise economizar recursos, como em um aplicativo móvel.

Não tenho certeza de que depende do formato XML, mas tenho certeza de que as implementações mais comuns do ApplicationContext são as XML, como ClassPathXmlApplicationContext, XmlWebApplicationContext e FileSystemXmlApplicationContext. Esses são os únicos três que eu já usei.

Se você estiver desenvolvendo um aplicativo Web, é seguro dizer que precisará usar o XmlWebApplicationContext.

Se você deseja que seus beans estejam cientes do Spring, você pode implementá-los como BeanFactoryAware e / ou ApplicationContextAware, para que você possa usar BeanFactory ou ApplicationContext e escolher qual interface implementar.


Esta é uma seção relevante da documentação. Como ApplicationContextinclui todas as funcionalidades do BeanFactory, geralmente é recomendado que ele seja usado em preferência ao BeanFactory, exceto em algumas situações limitadas, como em um Applet, onde o consumo de memória pode ser crítico e alguns kilobytes extras podem faça a diferença. No entanto, para a maioria dos aplicativos e sistemas corporativos 'típicos', ApplicationContexté isso que você deseja usar.
M. Atif Riaz

6

As diferenças entre BeanFactory e ApplicationContext são as seguintes:

  1. BeanFactory usa inicialização lenta, mas ApplicationContext usa inicialização ansiosa. No caso de BeanFactory, o bean é criado quando você chama o método getBeans (), mas o bean é criado antecipadamente no caso de ApplicationContext quando o objeto ApplicationContext é criado.
  2. O BeanFactory fornece explicitamente um objeto de recurso usando a sintaxe, mas o ApplicationContext cria e gerencia objetos de recurso por conta própria.
  3. O BeanFactory não suporta internatiolização, mas o ApplicationContext suporta internacionalização.
  4. Com a injeção de dependência baseada em anotação BeanFactory, não há suporte para injeção de dependência baseada em anotação, mas no ApplicationContext.

Usando BeanFactory:

BeanFactory beanfactory = new XMLBeanFactory(new FileSystemResource("spring.xml"));
 Triangle triangle =(Triangle)beanFactory.getBean("triangle");

Usando ApplicationContext:

ApplicationContext context = new ClassPathXMLApplicationContext("spring.xml")
Triangle triangle =(Triangle)context.getBean("triangle");

5

BeanFactory e ApplicationContext são maneiras de obter beans do contêiner IOC da primavera, mas ainda existem algumas diferenças.

BeanFactory é o contêiner real que instancia, configura e gerencia um número de beans. Esses beans geralmente colaboram entre si e, portanto, têm dependências entre si. Essas dependências são refletidas nos dados de configuração usados ​​pelo BeanFactory.

BeanFactory e ApplicationContext são interfaces Java e ApplicationContext estende BeanFactory. Ambos são configurados usando arquivos de configuração XML. Em resumo, o BeanFactory fornece recursos básicos de Inversão de controle ( IoC ) e Injeção de Dependência ( DI ), enquanto o ApplicationContext fornece recursos avançados recursos .

Um BeanFactory é representado pela interface " org.springframework.beans.factory " Onde BeanFactory, para o qual existem várias implementações.

ClassPathResource resource = new ClassPathResource("appConfig.xml");
XmlBeanFactory factory = new XmlBeanFactory(resource);

DIFERENÇA

  1. BeanFactory instancia o bean quando você chama o método getBean () , enquanto ApplicationContext instancia o feijão Singleton quando o contêiner é iniciado. Ele não espera que getBean () seja chamado.

  2. O BeanFactory não fornece suporte para internacionalização, mas o ApplicationContext fornece suporte para ele.

  3. Outra diferença entre BeanFactory vs ApplicationContext é a capacidade de publicar eventos em beans registrados como ouvintes.

  4. Uma das implementações populares da interface BeanFactory é XMLBeanFactory, enquanto uma das implementações populares da interface ApplicationContext é ClassPathXmlApplicationContext .

  5. Se você estiver usando a fiação automática e o BeanFactory, precisará registrar o AutoWiredBeanPostProcessor usando a API que você pode configurar em XML se estiver usando o ApplicationContext . Em resumo, o BeanFactory é bom para teste e não uso em produção, mas o ApplicationContext é uma implementação de contêiner mais rica em recursos e deve ser favorecida em relação ao BeanFactory

  6. BeanFactory por padrão, seu apoio preguiçoso carga e ApplicationContext pelo suporte padrão agressivo carregamento.


Você pode explicar seu número 1 com mais clareza, se eu defini um bean singleton no meu arquivo de configuração do spring, o contêiner do spring criará um singleton do mesmo, como importa se BeanFactory ou ApplicationContext está lá.
PJJ


3

uma. Uma diferença entre a fábrica de beans e o contexto do aplicativo é que o antigo somente instancia o bean quando você chama o método getBean () enquanto ApplicationContext instancia o bean Singleton quando o contêiner é iniciado. Ele não espera que o getBean seja chamado.

b.

ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");

ou

ApplicationContext context = new ClassPathXmlApplicationContext{"spring_dao.xml","spring_service.xml};

Você pode usar um ou mais arquivos xml, dependendo dos requisitos do seu projeto. Como eu estou aqui usando dois arquivos xml, ou seja, um para detalhes de configuração para classes de serviço, outras para classes dao. Aqui ClassPathXmlApplicationContext é filho de ApplicationContext.

c. O Container BeanFactory é um container básico, ele só pode criar objetos e injetar Dependências. Mas não podemos anexar outros serviços, como segurança, transação, mensagens etc. para fornecer todos os serviços que temos para usar o ApplicationContext Container.

d. O BeanFactory não fornece suporte para internacionalização, ou seja, o i18n, mas o ApplicationContext fornece suporte para ele.

e O BeanFactory Container não suporta o recurso AutoScanning (injeção de dependência baseada em anotações de suporte), mas o ApplicationContext Container suporta.

f. O contêiner do Beanfactory não criará um objeto de bean até o momento da solicitação. Isso significa que o Beanfactory Container carrega o feijão preguiçosamente. Enquanto o ApplicationContext Container cria objetos do bean Singleton somente no momento do carregamento. Isso significa que há carregamento antecipado.

g. O Container Beanfactory suporta apenas dois escopos (singleton e protótipo) dos beans. Mas o ApplicationContext Container suporta todo o escopo de beans.


Os pontos a e f são iguais. Podem ser combinados juntos.
dhana1310 24/03

3

Basicamente, podemos criar objetos de contêineres de mola de duas maneiras

  1. usando BeanFactory.
  2. usando ApplicationContext.

ambas são as interfaces,

usando classes de implementação, podemos criar objetos para contêineres de mola

chegando às diferenças

Fábrica de Feijão:

  1. Não suporta a injeção de dependência baseada em anotação.

  2. Não suporta I18N.

  3. Por padrão, seu suporte ao carregamento lento.

  4. não permite configurar para vários arquivos de configuração.

ex: contexto BeanFactory = novo XmlBeanFactory (novo recurso ("applicationContext.xml"));

ApplicationContext

  1. Injeção de dependência baseada em anotações de suporte.-@Autowired, @PreDestroy

  2. Suporte I18N

  3. Por padrão, suporta carregamento agressivo.

  4. Permite configurar vários arquivos de configuração.

ex:
contexto ApplicationContext = novo ClasspathXmlApplicationContext ("applicationContext.xml");


1

Consulte este documento no Spring Docs:

http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/beans.html#context-introduction-ctx-vs-beanfactory

5.15.1 BeanFactory ou ApplicationContext?

Use um ApplicationContext, a menos que você tenha um bom motivo para não fazer isso.

Como o ApplicationContext inclui todas as funcionalidades do BeanFactory, geralmente é recomendado sobre o BeanFactory, exceto em algumas situações, como em um Applet em que o consumo de memória pode ser crítico e alguns kilobytes extras podem fazer a diferença. No entanto, para os aplicativos e sistemas corporativos mais comuns, o ApplicationContext é o que você deseja usar. O Spring 2.0 e posterior fazem muito uso do ponto de extensão BeanPostProcessor (para efetuar proxies e assim por diante). Se você usar apenas um BeanFactory simples, uma quantidade razoável de suporte, como transações e AOP, não entrará em vigor, pelo menos não sem algumas etapas extras de sua parte. Essa situação pode ser confusa porque nada está realmente errado com a configuração.


1

O ApplicationContext é um irmão mais velho do BeanFactory, e tudo isso é fornecido pelo BeanFactory, além de muitas outras coisas.

Além dos recursos padrão do ciclo de vida org.springframework.beans.factory.BeanFactory, as implementações de ApplicationContext detectam e invocam beans ApplicationContextAware, bem como os recursos ResourceLoaderAware, ApplicationEventPublisherAware e MessageSourceAware.


1

Em um cenário em tempo real, a diferença entre o contêiner Spring IOC Core (BeanFactory) e o contêiner J2EE avançado (ApplicationContext) é a seguinte.

  1. BeanFactory criará objetos para os beans (ou seja, para classes POJO) mencionados no arquivo spring.xml ( <bean></bean>) somente quando você chamar o método .getBean (), mas considerando que ApplicationContext criará os objetos para todos os beans ( <bean></bean>se seu escopo não for mencionado explicitamente como "Protótipo") configurado no spring.xml ao carregar o próprio arquivo spring.xml.

  2. BeanFactory: (contêiner preguiçoso porque ele cria os objetos para os beans somente quando você chama explicitamente da classe principal / usuário)

    /*
     * Using core Container - Lazy container - Because it creates the bean objects On-Demand
     */
    //creating a resource
    Resource r = (Resource) new ClassPathResource("com.spring.resources/spring.xml");
    //creating BeanFactory 
    BeanFactory factory=new XmlBeanFactory(r);
    
    //Getting the bean for the POJO class "HelloWorld.java"
    HelloWorld worldObj1 = (HelloWorld) factory.getBean("test");

    ApplicationContext: (contêiner ansioso devido à criação dos objetos de todos os beans singleton ao carregar o próprio arquivo spring.xml)

    ApplicationContext context = new ClassPathXmlApplicationContext("com/ioc/constructorDI/resources/spring.xml");
  3. Tecnicamente, é recomendável usar o ApplicationContext porque, em aplicativos em tempo real, os objetos do bean serão criados enquanto o aplicativo é iniciado no próprio servidor. Isso reduz o tempo de resposta para a solicitação do usuário, pois os objetos já estão disponíveis para responder.


O Stack Overflow não é um fórum, por isso editei sua resposta para responder mais diretamente à pergunta e evitar convidar discussões.
26416 Jeffrey Bosboom


0

use o BeanFactory para aplicativos que não sejam da Web porque ele suporta apenas os escopos de bean Singleton e Prototype.

Enquanto o contêiner ApplicationContext suporta todos os escopos de bean, você deve usá-lo para aplicativos da web.


0

Em suma:

O ApplicationContext inclui todas as funcionalidades do BeanFactory. É geralmente recomendado usar o primeiro.

Existem algumas situações limitadas, como em um aplicativo móvel, em que o consumo de memória pode ser crítico.

Nesses cenários, pode ser justificável usar o BeanFactory mais leve . No entanto, na maioria dos aplicativos corporativos, o ApplicationContext é o que você deseja usar.

Para mais, veja minha postagem no blog:

Diferença entre BeanFactory e ApplicationContext no Spring - o blog do java spring do básico


0

Eu preciso explicar o BeanFactory & ApplicationContext.

BeanFactory: BeanFactory é a interface raiz para acessar o SpringBean Container. Há uma visão básica do cliente de um contêiner de bean. Essa interface é implementada pela classe de objeto que contém o número de definições de beans e cada uma é identificada exclusivamente pelo nome da String.
Dependendo da definição do Bean, a fábrica retornará a instância em que a instância pode ser a instância do objeto contido ou uma única instância compartilhada. O tipo de instância que será retornado depende da configuração da fábrica de bean.
Normalmente, a fábrica do Bean carregará toda a definição de todos os beans, armazenados na fonte de configuração como XML ... etc.

BeanFactory é um contêiner mais simples que fornece o suporte básico para Injeção de Dependência

Contexto do Aplicativo aplicativo O contexto do aplicativo é uma interface central com o aplicativo spring que fornece as informações de configuração para o aplicativo. Ele implementa a interface de fábrica de feijão.

O contexto do aplicativo é um contêiner avançado, que adiciona um nível avançado de funcionalidade específica à empresa, como a capacidade de resolver a mensagem de texto do arquivo de propriedades ... etc

Um ApplicationContext fornece:

Métodos de fábrica de bean para acessar componentes de aplicativos. Herdado de ListableBeanFactory. A capacidade de carregar recursos de arquivo de maneira genérica. Herdado da interface ResourceLoader. A capacidade de publicar eventos para ouvintes registrados. Herdado da interface ApplicationEventPublisher. A capacidade de resolver mensagens, apoiando a internacionalização. Herdado da interface MessageSource. Herança de um contexto pai. Definições em um contexto descendente sempre terão prioridade. Isso significa, por exemplo, que um contexto pai único pode ser usado por um aplicativo Web inteiro, enquanto cada servlet possui seu próprio contexto filho, independente do de qualquer outro servlet. Além dos recursos padrão do ciclo de vida do BeanFactory,

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.