Spring中的FactoryBean实现原理详解
作者:军伟@
1、概述
spring中有两种类型的Bean:
- 一种是普通的JavaBean;
- 另一种就是工厂Bean(FactoryBean)
这两种Bean都受Spring的IoC容器管理,但它们之间却有一些区别。
2、详述
普通的JavaBean不再多说,我们将其定义好,然后在配置文件中定义并配置其依赖关系,就可以通过IoC容器的getBean获取到。
那么FactoryBean呢?
FactoryBean跟普通Bean不同,它是实现了FactoryBean<T>接口的Bean,通过BeanFactory类的getBean方法直接获取到的并不是该FactoryBean的实例,而是该FactoryBean中方法getObject返回的对象。但我们可以通过其它途径获取到该FactoryBean的实例,方法就是在通过getBean方法获取实例时在参数name前面加上“&”符号即可。
FactoryBean接口提供的方法如下:
public interface FactoryBean<T> { //获取FactoryBean初始化的Bean实例 T getObject() throws Exception; //获取Bean实例的类型 Class<?> getObjectType(); //判断是否是单例模式 boolean isSingleton(); }
3、示例
创建MyFactoryBean
public class MyFactoryBean implements FactoryBean<Date>,BeanNameAware { private String name; @Override public Date getObject() throws Exception { return new Date(); } @Override public Class<?> getObjectType() { return Date.class; } @Override public boolean isSingleton() { return false; } public void sayName() { System.out.println("My name is " + this.name); } @Override public void setBeanName(String name) { this.name = name; } }
在Spring的配置文件ApplicationContext.xml中注入MyFactoryBean
<bean id ="myFactoryBean" class="com.xxxx.MyFactoryBean"></bean>
测试代码
public class MainFactoryBean { @SuppressWarnings("resource") public static void main(String [] args){ ApplicationContext appCtx = new ClassPathXmlApplicationContext("applicationContext.xml"); Date now = (Date) appCtx.getBean("myFactoryBean"); System.out.println(now); MyFactoryBean factoryBean = (MyFactoryBean) appCtx.getBean("&myFactoryBean"); factoryBean.sayName(); } }
运行结果
通过myFactoryBean名称获取到的Bean是Date对象实例,通过&myFactoryBean获取到的是MyFactoryBean对象实例。
4、实现原理
我们来看一下执行Date now = (Date) appCtx.getBean("myFactoryBean"); 时会做的处理操作。 AbstractBeanFactory中会进行一系列的操作。
getBean获取bean
@Override public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); }
doGetBean中获取bean实例
protected <T> T doGetBean( final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException { .........//省略部分代码 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); .........//省略部分代码 return (T) bean; }
getObjectForBeanInstance中会选择bean实例是普通的Bean还是FactoryBean,同时通过判断name中是否有&来选择判断是或者FactoryBean还是其getObject方法中获取的bean
protected Object getObjectForBeanInstance( Object beanInstance, String name, String beanName, RootBeanDefinition mbd) { .........//省略部分代码 //判断bean类型是否是FactoryBean,或者name是否是以&开头,如果是则直接返回 if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) { return beanInstance; } //如果是则从getObjectFromFactoryBean中获取 if (object == null) { // Return bean instance from factory. FactoryBean<?> factory = (FactoryBean<?>) beanInstance; if (mbd == null && containsBeanDefinition(beanName)) { mbd = getMergedLocalBeanDefinition(beanName); } boolean synthetic = (mbd != null && mbd.isSynthetic()); object = getObjectFromFactoryBean(factory, beanName, !synthetic); } return object; }
getObjectFromFactoryBean接下来会执行FactoryBean的getObject方法获取bean了。
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) { .........//省略部分代码 Object object = doGetObjectFromFactoryBean(factory, beanName); .........//省略部分代码 return object; } private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName) throws BeanCreationException { Object object; .........//省略部分代码 //调用Factory的getObject方法 object = factory.getObject(); .........//省略部分代码 return object; }
总结
Spring对FactoryBean的实现机制是当你获取一个Bean时,如果获取的Bean的类型是FactoryBean,并且其name中并没有&则调用bean的getObject方法获取FactoryBean实现类中提供bean,否则就是直接返回普通的bean类型。
到此这篇关于Spring中的FactoryBean实现原理详解的文章就介绍到这了,更多相关FactoryBean实现原理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
您可能感兴趣的文章:
- Spring中的BeanFactory与FactoryBean区别详解
- SpringBoot升级3.2报错Invalid value type for attribute ‘factoryBeanObjectType‘: java.lang.String的解决方案
- Spring中的FactoryBean与ObjectFactory详解
- Spring中BeanFactory与FactoryBean的区别解读
- Spring中的FactoryBean与BeanFactory详细解析
- Spring的FactoryBean<Object>接口示例代码
- 简单了解Spring中BeanFactory与FactoryBean的区别