[注]本文转译自http://geekabyte.blogspot.com/2014/11/difference-between-beanfactory-and.html

本文主旨是阐明Spring框架中的FactoryBean和BeanFactory两个接口的区别,但首先来扯一下Spring的大致构成。

Spring涉及的东西很多,但就其核心那要数依赖注入了,依赖注入容器由以下四个组件构成:

  1.org.springframework.core,这个包里是基本功能实现,如异常、版本探测等;

  2.org.springframework.beans,这里是管理bean的一些接口和类,FactoryBean就在这个包下;

  3.org.springframework.context,这个包构建于org.springframework.beans之上,ApplicationContext就实现了BeanFactory;

  4.org.springframework.expression,这个包提供了Spring的表达式语言;

Springframework的核心架构是这样的,

  IoC的容器就实现在Spring-Beans包里,支持Spring-Core的功能,Spring-Context是基于Spring-Core和Spring-Beans来扩展的,所以引入Spring-Context包就自然地引入了Spring-Core和Spring-Beans的IoC容器。

  org.springframework.beans管理着bean的创建,注入等,FactoryBean接口就在这个包中,而BeanFactory接口在子包org.springframework.beans.factory中。

转入主题,FactoryBean和BeanFactory有什么区别呢?

  实际上这两个接口有完全不同的目的,FactoryBean这个接口是当你实现工厂接口时,期望把FactoryBean创建的对象托管给spring管理;而BeanFacrory接口是一个工厂,代表的是IoC容器,它的扩展实现(如,ClassPathXmlApplicationContext)管理着我们创建的beans,并提供了多种途径来获取我们想要的具名的bean。大多数情况下,我们都不会直接去实现BeanFactory这个接口,除非你想要扩展Spring容器的核心功能集,但是如果想要让spring帮助管理由factory创建的对象时,我们就需要FactoryBean了。

  简言之,BeanFactory可视为IoC容器,FactoryBean是一个工厂类,它创建的对象将被注册到容器中从而得到IoC容器的管理。

现用两个简单的代码片段来辅助解释

  1.FactoryBean

  先来看一下这个接口的定义,3.0后支持泛型,

package org.springframework.beans.factory;

public interface FactoryBean<T> {
    T getObject() throws Exception;

    Class<?> getObjectType();

    boolean isSingleton();

}

  再来看一片配置文件片断,

<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
 
  <!-- the data source -->
  <property name="dataSource" ref="dataSource"></property>
        
  <!-- configuration that specifies the JPA Adapter to use -->
  <property name="jpaVendorAdapter">
    <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
    </bean>
  </property>
  
  <!-- configuration to specify JPA behaviors -->
  <property name="jpaProperties">
  <props>
    <prop key="hibernate.hbm2ddl.auto">create-drop</prop>
    <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
  </props>
  </property>
</bean>

  如果去读LocalContainerEntityManagerFactoryBean的源码,你会发现这个类并没有jpaVendorAdapter这些属性,那为什么会出现这些属性呢?

  这是因为LocalContainerEntityManagerFactoryBean实现了FactoryBean接口,spring不会返回LocalContainerEntityManagerFactoryBean本身,而是通过#getObject返回了EntityManagerFactory这个类型的一个对象,才有我们看到的那么多属性可配置。

  2.BeanFactory

  先看下这个接口的代码,

package org.springframework.beans.factory;

import org.springframework.beans.BeansException;

public interface BeanFactory {

    /**
     * Used to dereference a {@link FactoryBean} instance and distinguish it from
     * beans <i>created</i> by the FactoryBean. For example, if the bean named
     * <code>myJndiObject</code> is a FactoryBean, getting <code>&myJndiObject</code>
     * will return the factory, not the instance returned by the factory.
     */
    String FACTORY_BEAN_PREFIX = "&";

    Object getBean(String name) throws BeansException;

    <T> T getBean(String name, Class<T> requiredType) throws BeansException;

    <T> T getBean(Class<T> requiredType) throws BeansException;

    Object getBean(String name, Object... args) throws BeansException;

    boolean containsBean(String name);

    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException;

    Class<?> getType(String name) throws NoSuchBeanDefinitionException;

    String[] getAliases(String name);
}

  注意,标红的

    String FACTORY_BEAN_PREFIX = "&";

  这个属性是专门为FactoryBean设置的,正如1中说到,FactoryBean的实现类默认返回的对象是#getObject的类弄,如果我们就要返回FactoryBean的实现本身的实例呢?于是,就要用到这个前缀&了,

ApplicationContext context=
new ClassPathXmlApplicationContext("classpath:foo-config.xml");
FooFactoryBean ffb=context.getBean("&fooFactoryBean"); //从这里可以看出BeanFactory和FactoryBean的关系,spring Bean工厂BeanFactory管理着包括FactoryBean实例的所有bean,而FactoryBean又是特殊的,厂长还专门给这个bean设置了标记&.

  接着说这个ClassPathXmlApplicationContext实现了ApplicationContext,而ApplicationContext实现了BeanFactory:

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
        MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
posted on 2015-08-23 16:57  ijo  阅读(438)  评论(0)    收藏  举报