spring官网笔记7

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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值