Spring容器的扩展点(二)FactoryBean
我们还是先看一下官网上是怎么说的:
从上面这段文字我们可以得出几个信息
1、FactoryBean主要是用来定制化Bean的创建逻辑
2、当我们实例化一个Bean的逻辑很复杂的时候,使用FactoryBean是很有必要的,这样可以规避我们去使用冗长的XML配置
3、FactoryBean提供了以下三个方法
T getObject() throws Exception;//返回这个FactoryBean所创建出来的对象
Class<?> getObjectType();//返回这个FactoryBean所创建的对象类型,如果我们能确认返回对象的类型的话,我们应该正常对这个方法做出实现,而不是返回null
default boolean isSingleton() {//返回FactoryBean所创建的对象是否是单例,默认是true
return true;
}
1、Spring自身大量使用了FactoryBean这个概念,至少有50个FactoryBean的实现类存在于spring的容器中
2、假设我们定义一个FactoryBean,名为myFactoryBean,当我们调用getBean(“myFactoryBean”)时返回的并不是这个FactoryBean而是这个FactoryBean所创建的bean。如果我们想获得FactoryBean本身需要在名字前面加个&。形如这种形式:getBean(“&myFactoryBean”)
上面这些概念说起来很抽象,不是很明白,下面我们通过一些应用更了解FactoryBean
public class Main07 {
public static void main(String[] args) {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
System.out.println(ac.getBean("myFactoryBean"));
System.out.println(ac.getBean("&myFactoryBean"));
}
}
@Component
public class MyFactoryBean implements FactoryBean {
@Override
public Object getObject() throws Exception {
System.out.println("执行了一段复杂的逻辑");
return new TestBean();
}
@Override
public Class<?> getObjectType() {
return TestBean.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
public class TestBean {
public TestBean(){
System.out.println("Test Bean 被创建出来了");
}
}
输出结果为:
执行了一段复杂的逻辑
Test Bean 被创建出来了
com.phr.factorybean.TestBean@2aaf7cc2
com.phr.factorybean.MyFactoryBean@6e3c1e69
我们虽然没有将testBean直接放入spring容器中,但是通过FactoryBean也达到了这样一个效果。同时当我们直接调用getBean(“myFactoryBean”)返回的是创建的对象,而ac.getBean("&myFactoryBean")返回的是对象本身。
涉及到FactoryBean的源码
// 循环bd,实例化单例bean
for (String beanName : beanNames) { // userService
// 对beanDefinition进行合并,基于合并后的BeanDefinition去创建bean
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 非抽象,单例,非懒加载
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 判断是不是一个SmartFactoryBean
if (isFactoryBean(beanName)) {
// 如果是一个FactoryBean,那么则获取LubanFactoryBean对象
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
// eager:急切的意思,立马初始化
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
// 根据beanName去生成FactoryBean中所生成的Bean对象
getBean(beanName);
}
}
}
else {
// 根据beanName去创建bean
getBean(beanName);
}
}
}
public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {
String beanName = transformedBeanName(name); // 如果name是&xxx,那么则返回xxx,再根据xxx去判断对应的到底是不是一个FactoryBean
// 从单例池中获取bean对象,并判断是不是FactoryBean
Object beanInstance = getSingleton(beanName, false);
if (beanInstance != null) {
return (beanInstance instanceof FactoryBean);
}
// 如果本BeanFactory不存在该bean,则判断父BeanFactory中是否存在,递归
// No singleton instance found -> check bean definition.
if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
// No bean definition found in this factory -> delegate to parent.
return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);
}
// 如果beanName对应的Bean对象还没有生成,则先合并BeanDefinition,再根据BeanDefinition判断是不是FactoryBean
return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
}
1、如果是一个FactoryBean那么在getBean时,添加前缀“&”获取这个FactoryBean
2、判断是不是一个smartFactoryBean。并且不是懒加载的。
这里涉及到一个概念,就是smartFactoryBean,这个接口继承自FactoryBean接口,并且时FactoryBean的唯一子接口,它扩展了Factory的两个方法,如下
default boolean isPrototype() {//默认不是原型
return false;
}
default boolean isEagerInit() {//默认不急切初始化
return false;
}
从上面的代码不难看出,我们只实现FactoryBean接口,Spring并不会在启动时将这个FactoryBean所创建的创建出来。
实际上我们发现,当我们仅仅实现FactoryBean时,其getObject()创建出来的Bean是懒加载的Bean
lse;
}
从上面的代码不难看出,我们只实现FactoryBean接口,Spring并不会在启动时将这个FactoryBean所创建的创建出来。
实际上我们发现,当我们仅仅实现FactoryBean时,其getObject()创建出来的Bean是懒加载的Bean
1、如果是一个SmartFactoryBean并且不是懒加载的,那么创建这个Factory创建的bean,此时创建的不是FactoryBean,而是getObject()返回的bean