两者区别
- 共同点:BeanFactory 和 FactoryBean 两者都是接口
package org.springframework.beans.factory; public interface FactoryBean<T> { String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType"; /** * Return an instance (possibly shared or independent) of the object * managed by this factory. */ @Nullable T getObject() throws Exception; /** * Return the type of object that this FactoryBean creates, * or {@code null} if not known in advance. */ @Nullable Class<?> getObjectType(); /** * Is the object managed by this factory a singleton? That is, * will {@link #getObject()} always return the same object * (a reference that can be cached)? */ default boolean isSingleton() { return true; } }
package org.springframework.beans.factory; public interface BeanFactory { String FACTORY_BEAN_PREFIX = "&"; // Return an instance, which may be shared or independent, of the specified bean. Object getBean(String name) throws BeansException; // Return an instance, which may be shared or independent, of the specified bean. <T> T getBean(String name, Class<T> requiredType) throws BeansException; // Return an instance, which may be shared or independent, of the specified bean. Object getBean(String name, Object... args) throws BeansException; // Return the bean instance that uniquely matches the given object type, if any. <T> T getBean(Class<T> requiredType) throws BeansException; // Return an instance, which may be shared or independent, of the specified bean. <T> T getBean(Class<T> requiredType, Object... args) throws BeansException; /** * Return a provider for the specified bean, allowing for lazy on-demand retrieval * of instances, including availability and uniqueness options. */ <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType); /** * Return a provider for the specified bean, allowing for lazy on-demand retrieval * of instances, including availability and uniqueness options. */ <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType); boolean containsBean(String name); boolean isSingleton(String name) throws NoSuchBeanDefinitionException; boolean isPrototype(String name) throws NoSuchBeanDefinitionException; /** * Check whether the bean with the given name matches the specified type. * More specifically, check whether a {@link #getBean} call for the given name * would return an object that is assignable to the specified target type. */ boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException; boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException; /** * Determine the type of the bean with the given name. More specifically, * determine the type of object that {@link #getBean} would return for the given name. */ @Nullable Class<?> getType(String name) throws NoSuchBeanDefinitionException; /** * Determine the type of the bean with the given name. More specifically, * determine the type of object that {@link #getBean} would return for the given name. */ @Nullable Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException; // Return the aliases for the given bean name, if any. String[] getAliases(String name); }
- 不同点:
- BeanFactory:表示一个 Bean 的工厂,用来管理 Bean 的工厂,Spring中,所有的 Bean 都是由 BeanFactory 进行管理的,也就是 Ioc 容器。通过 getBean() 方法可以得到一个对象的 Bean。
BeanFactory beanFactory = new ClassPathXmlApplicationContext("xxx"); beanFactory.getBean(xxx.class);
- FactoryBean:它是一个 Bean,可以用于产生对象或者用于修饰对象的工厂 Bean。也就是说,一个类如果实现了 FactoryBean,那么这个类中存在两个对象,一个是 getObject() 方法返回的 Object(TempDaoFactoryBean),另一个是当前对象 (DaoFactoryBean)。
public class TempDaoFactoryBean { public void test() { System.out.println("FactoryBean"); } } //---------------------------------------------- @Component("daoFactoryBean") public class DaoFactoryBean implements FactoryBean { @Override public Object getObject() throws Exception { return new TempDaoFactoryBean(); } @Override public Class<?> getObjectType() { return TempDaoFactoryBean.class; } @Override public boolean isSingleton() { return false; } public void testBean() { System.out.println("testBean"); } }
- 注意:getObject() 得到的对象存储的是当前类指定的名字,如果在调用 getBean() 时,在当前类 (DaoFactoryBean) 的前边加上字符 &,那么可以调用当前对象。
DaoFactoryBean daoFactoryBean = (DaoFactoryBean) context.getBean("&daoFactoryBean"); daoFactoryBean.testBean(); // 不加字符 &,只能调用指定的类 TempDaoFactoryBean tempDaoFactoryBean = (TempDaoFactoryBean) context.getBean("daoFactoryBean"); tempDaoFactoryBean.test();
使用场景
BeanFactory:大部分情况我们只会用到 BeanFactory,直接调用 getBean() 方法就可以得到这个对象的实例,从而调用这个对象中的方法。
FactoryBean:当一个类的依赖关系很复杂的时候,我们又想对外提供简单的配置关系(外部可以配置这个类),可以使用 FactoryBean。
例如:sqlSessionFactoryBean,这个类实现了 FactoryBean,我们不需要去维护 sqlSessionFactoryBean 类的依赖关系,把它交给 FactoryBean,我们只需要调用实现 FactoryBean 的这个类就能实现简单配置,从而可以使用这个类,平时我们配置 MyBatis 最简单的,就是只需要添加 MySQL 的 user、password、driverClass、jdbcUrl,其他的则不需要我们关心。
有兴趣的同学可以关注我的个人公众号,期待我们共同进步!!!