参见原文:http://www.geekabyte.io/2014/11/difference-between-beanfactory-and.html
Codes and Rants | Javascript, Java and Scala
Saturday, November 15, 2014
Difference between BeanFactory and FactoryBean in Spring Framework
tl;dr A FactoryBean is an interface that you, as a developer, implements when writing factory classes and you want the object created by the factory to be managed as a bean by Spring, while a BeanFactory on the other hand, represents the Spring IoC container, it contains the managed beans and provides access to retrieving them. It is part of the core of the framework which implements the base functionality of an inversion of control container.
This post clarifies the difference between BeanFactory and FactoryBean in Spring Framework, and in the processes sheds some light on how the core component of Spring Frameworks stack together.
The Spring Framework has grown to be a lot of things, but at its core, it is a very versatile Dependency Injection container, upon which other things get built on. This core, this dependency injection container is actually built from 4 components.
1. The org.springframework.core package. In which, base functionalities that cut across the whole framework is implemented, e.g. exceptions, version detection etc.
2. The org.springframework.beans package. In which we have interfaces and classes for managing Java beans. The BeanFactory interface is found here.
3. The org.springframework.context Package. This builds on the beans package. An example of an interface out of this package that you would have used is the ApplicationContext (it implements the BeanFactory interface)
4. The org.springframework.expression package. This provides the expression language that can be used to traverse and manipulate the object graph within the container at runtime.
Diagrammatically this would look thus:
The places where the IoC container mechanism is implemented is mainly in Spring-Beans
package with supporting base functionality from Spring-Core and (Spring-Context builds on these two, extending it and adding additional functionalities certain). By the way, the fact that Spring-Context builds on Spring-Core and Spring-Beans is why only including Spring-Context as a dependency is all you need to get access to the Spring IoC container functionality in your application.
The functionality for creating, wiring and managing beans are packed into the org.springframework.beans. It is in this package we have BeanFactory and in a sub package (org.springframework.beans.factory) that you would find FactoryBean. The two interfaces that are the subject of this post.
The question then is, how does the BeanFactory and FactoryBean interfaces differ?
Apart from the fact that they share the same root package and are both anagrams (which make them confusing), they serve two totally different purposes.
A FactoryBean is an interface that you, as a developer, implements when writing factory classes and you want the object created by the factory class to be managed as a bean by Spring, while a BeanFactory on the other hand, represents the Spring IoC container, it contains the managed beans and provides access to retrieving them. It is part of the core of the framework which implements the base functionality of an inversion of control container.
In most cases, you won't find yourself using or implementing the BeanFactory interface directly, unless you are extending the core functionality of the framework. While you would do implement the FactoryBean when you have objects that are created by Factories that needs to be managed by Spring.
In more succinct words, the BeanFactory represents the Spring container while the FactoryBean represents factory classes whose created object are picked up and registered as a bean in the container.
To get more feel of these two, let us quickly take a look at two instances from the framework where they are put to use:
LocalContainerEntityManagerFactoryBean as an example of a FactoryBean
In configuring Hibernate JPA in Spring Framework, I mentioned the role of the org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean in the configuration process when creating a container managed EntityManagerFactory. It is the class that is wired up in the configuration. E.g:
<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>
But if you look at the configuration, the class that is being wired up is of type LocalContainerEntityManagerFactoryBean, how come, it then produces a bean of type EntityManagerFactory?
That is because LocalContainerEntityManagerFactoryBean is a factory that creates and returns an object of type EntityManagerFactory. And because it implements FactoryBeaninterface, when configured, the Spring container knows that the registered bean won't be of type LocalContainerEntityManagerFactoryBean, but the type it returns in its getObject() method.
That is an example of what FactoryBean is used for.
ClassPathXmlApplicationContext as an example of BeanFactory.
The ClassPathXmlApplicationContext is one of the ways you can initiate Springs IoC container. You supply it with the configuration(s), it does the necessary object resolution and dependency injection and returns to you a container from which you can retrieve a fully resolved bean.
For example:
ApplicationContext context =
new ClassPathXmlApplicationContext("classpath:context-config.xml");
ClassPathXmlApplicationContext is of type ApplicationContext, and the ApplicationContext interface itself is found in the Spring-Context (refer to the diagram above).
The Spring-Context module part of the core component, contains classes and interfaces that provides enhanced functionality over the Spring-Beans and Spring-Core modules. The ApplicationContext interface is one of such convenience found in the Spring-Context module as it defines amongst various functionalities, the ability to retrieve beans from the container, ability to load file resources in a generic fashion, internationalization support etc...
But the ApplicatonContext interface is itself a type of BeanFactory as it extends the BeanFactory interface indirectly by extending the ListableBeanFactory and HierarchicalBeanFactory, as its signature shows:
Which means whenever you use any of the classes that implements the ApplicationContext(ClassPathXmlApplicationContext, FileSystemXmlApplicationContext, etc) you are accessing and using the Spring Container, through interfaces that are extension of the base BeanFactory interface.