spring源码分析——BeanFactory与FactoryBean的区别

  BeanFactory是spring容器的顶层bean工厂,它提供了从容器获取bean,判断是否存在bean的一些简单方法。FactoryBean是创建

Bean对象的一种方式,如果我们不希望通过扫描注册,就可以使用这种方式注册Bean。

一:BeanFactory接口

 这个接口类提供getBean,containsBean,isSingleton,isPrototype等简单的操作

public interface BeanFactory {

	 
	String FACTORY_BEAN_PREFIX = "&";


	Object getBean(String name) throws BeansException;

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

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

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

	 
	<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
 
	<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);

	 
	<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);

	 
	boolean containsBean(String name);

	 
	boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

	 
	boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

	 
	boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;

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

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

	 
	String[] getAliases(String name);

}  

我们spring容器拉起的过程中,使用它的子类比较多,

快捷键Ctrl + alt + u 可以查询类的继承关系

spring源码分析——BeanFactory与FactoryBean的区别

而ApplicationContext与BeanFactory的关系,就是ApplicatationContext在BeanFactroy提供功能的基础上做了一些扩展,比如国际化的操作,解析等

spring源码分析——BeanFactory与FactoryBean的区别

写个测试类,测试一下拿到的beanFactory对象:

@Component
public class BeanFactoryTest implements BeanFactoryAware {

	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
		System.out.println("beanFactory: "+beanFactory);
		System.out.println("student: "+beanFactory.getBean("student"));
	}

}

  

spring源码分析——BeanFactory与FactoryBean的区别

 实际注入的是DefaultListableBeanFactory这个工厂对象,通过这个工厂容器可以拿到bean对象。

二:FactoryBean接口

实现FactoryBean接口,这个接口内有三个方法,getObject,实际创建的对象,getObjectType对象类型,isSingleton是否单例

@Component
public class MyFactoryBean implements FactoryBean<User> {

	public User getObject() throws Exception {
		return new User();
	}

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

	public boolean isSingleton() {
		return true;
	}
}

  

测试代码:

spring源码分析——BeanFactory与FactoryBean的区别

通过运行结果可以看出,beanName为myFactoryBean时,实际返回的是getObject方法的对象,如果想要获取MyFactoryBean本身的对象,需要加上&符号 

spring源码分析——BeanFactory与FactoryBean的区别

下面我们来分析一下源码怎么实现的?

先来看一下预实例化的时候,判断是否是FactoryBean,

spring源码分析——BeanFactory与FactoryBean的区别

spring源码分析——BeanFactory与FactoryBean的区别

 spring源码分析——BeanFactory与FactoryBean的区别

 判断是否是FactoryBean接口的实例,很显然,MyFactoryBean是的,然后调用getBean实例化这个对象,beanName前面加上&,就是实例化自身的对象

spring源码分析——BeanFactory与FactoryBean的区别

实例化完成后

spring源码分析——BeanFactory与FactoryBean的区别

spring源码分析——BeanFactory与FactoryBean的区别

 直接返回这个实例对象,只有是FactoryBean对象,同时没有&符合时,才会去调用getObject方法,

看一下没有&符号的getBean:

spring源码分析——BeanFactory与FactoryBean的区别

因为已经预实例化,所以缓存中存在MyFactoryBean这个对象,走到getObjectForBeanInstance这个方法

 spring源码分析——BeanFactory与FactoryBean的区别

 spring源码分析——BeanFactory与FactoryBean的区别

spring源码分析——BeanFactory与FactoryBean的区别

调用getObject方法获取真实的对象,这样实际上返回的是User对象。

spring源码分析——BeanFactory与FactoryBean的区别

如果前面加上&符号时,返回的是本身的对象,我们来分析一下

spring源码分析——BeanFactory与FactoryBean的区别

spring源码分析——BeanFactory与FactoryBean的区别

 因为是以&开头的,所以直接返回这个实例对象,而没有去调用getObject方法。

spring源码分析——BeanFactory与FactoryBean的区别

 spring源码分析——BeanFactory与FactoryBean的区别

 spring源码分析——BeanFactory与FactoryBean的区别

 以上便是获取FactoryBean本身对象的过程。

上面都是单例的情况,如果isSingleton是false呢

spring源码分析——BeanFactory与FactoryBean的区别

 spring源码分析——BeanFactory与FactoryBean的区别

 如果是isSingleton为false或者母体类就是非单例,那么直接getObject返回,跟缓存没有关系

spring源码分析——BeanFactory与FactoryBean的区别

 以上就是从源码层面分析了FactoryBean的使用以及如何实现,这个接口在mybatis等和spring整合的框架中应用比较多。