FactoryBean和BeanFactory

116 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第16天,点击查看活动详情

面试经常遇到,虽说是老生常谈,但必须掌握啊。

BeanFactory

首先BeanFactory是一个接口,接口出现的目的就是为了扩展。
想要了解BeanFactory是必须要知道SingletonBeanRegistry接口的,SingletonBeanRegistry可以直称他为单例池,因为它就是Spring IOC存放bean的地方,其子实现类DefaultSingletonBeanRegistry中便定义了大名鼎鼎的三级缓存,其实也就是三个Map,本章不讲三级缓存,不作描述。

从图中可以看出,有BeanFactory实现了SingletonBeanRegistry,已知SingletonBeanRegistry是存放Bean实例的地方,那BeanFactory实现SingletonBeanRegistry,无非是想创建bean和获取bean。
熟悉IOC流程的都应该知道,Spring会解析Bean的定义信息生成BeanDefinition存放在BeanFactory中,而getBean时会经过实例化、填充属性、初始化创建这个Bean,然后放在单例池中再返回。
由此我们知道在Spring中所有的Bean都是由BeanFactory管理的。
Sprign有提供好多BeanFactory的实现,其中就包括ApplicationContext,说BeanFactory是Spring的心脏,那ApplicationContext则可以说是Spring的躯体了。
ApplicationContext既然有实现BeanFactory,肯定能提供BeanFactory所有的功能,除此之外,ApplicationContext还提供了许多其他功能。

BeanFactory中提供的方法如下:

FactoryBean

FactoryBean是一个接口,其主要目的是自定义Bean的过程,可以实现此接口来完成实例化过程比较复杂的bean的创建。

public interface FactoryBean<T> {

	String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";

	@Nullable
	T getObject() throws Exception;

	@Nullable
	Class<?> getObjectType();

	default boolean isSingleton() {
		return true;
	}

}

怎么理解呢, 就是实现此接口的bean不能用作普通bean,此bean要暴露的是其实现类中getObject中自定义创建的类,而不是它自身。

@Component
public class UserFactoryBean implements FactoryBean<User> {

    @Override
    public User getObject() throws Exception {
        // 假设User的实例化过程比较复杂,在此处进行User的实例化
        return new User();
    }

    @Override
    public Class<?> getObjectType() {
        return User.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}
    public static void main(String[] args) {
        AnnotationConfigApplicationContext cfg = new AnnotationConfigApplicationContext(Application.class);
        Object user = cfg.getBean("userFactoryBean");		//获得的是User实例
        Object user = cfg.getBean("&userFactoryBean");	//获得的是UserFactoryBean实例
    }

通多demo可以看出,通过beanName获取到的实际上是getObject()方法返回的User实例。
通过“&”+beanName获取到的才是UserFactoryBean实例。

总结:FactoryBean是Spring提供的一种古老的Bean的创建方式,是对Bean的一种扩展。为什么说它古老,因为它是在2003年古老的版本中就存在了,毕竟我们现在都是JavaConfig形式创建Bean了。 FactoryBean的底层源码我就不作分析了,感谢。