05 Spring 源码总结 - FactoryBean

整体概述

FactoryBean 与 BeanFactory 区别

两者都是用作创建对象

  • 使用 BeanFactory 的时候必须要遵循完整的创建过程,这个过程由spring来管理控制
  • 使用 FactoryBean 只需要调用getObject()就可以返回具体的对象,整个对象的创建过程是由用户自己来控制,更加灵活

FactoryBean 类方法

在这里插入图片描述

拓展实践

1. 创建 User 对象

public class User {

    private String username;

    public User() {
    }

    public User(String username) {
        this.username = username;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                '}';
    }
}

2. 创建 FactoryBean 实现类 MyFactoryBean

public class MyFactoryBean implements FactoryBean<User> {

    @Override
    public User getObject() throws Exception {
        //任何创建对象的操作
        return new User("zhangsan");
    }

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

    @Override
    public boolean isSingleton() {
        return true;
    }
}

3. 新建配置文件 factoryBean.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="myFactoryBean" class="com.mashibing.MyFactoryBean">

    </bean>
</beans>

4. 测试类

public class Test {

    public static void main(String[] args) {
        MyClassPathXmlApplicationContext ac = new MyClassPathXmlApplicationContext("factoryBean.xml");

        MyFactoryBean bean1 = (MyFactoryBean) ac.getBean( "&myFactoryBean");
        System.out.println(bean1);

        User bean = (User) ac.getBean("myFactoryBean");
        System.out.println(bean.getUsername());

        User bean2 = (User) ac.getBean("myFactoryBean");
        System.out.println(bean2.getUsername());
        }
}

概要解析

实现 FactoryBean 的类包含了几个对象

  1. 实现 FactoryBean 接口的对象,即 MyFactoryBean
  2. 通过 getObject() 方法返回的对象,即 User

两个对象都由 Spring 管理,其中 MyFactoryBean 存放在一级缓存 singletonObjects 中,User 存放在 factoryBeanObjectCache

在这里插入图片描述


MyFactoryBean bean1 = (MyFactoryBean) ac.getBean( “&myFactoryBean”) 执行流程

在这里插入图片描述
在这里插入图片描述

(1)String beanName = transformedBeanName(name);
在doGetBean() 中 先取得去掉 name 中前缀 “&” 的 beanName

(2)Object sharedInstance = getSingleton(beanName);
然后通过 getSingleton(beanName) 从一级缓存中得到 MyFactoryBean 对象

(3)调用 getObjectForBeanInstance(sharedInstance, name, beanName, null)
从 beanInstannce 中获取公开的Bean对象,主要处理beanInstance是FactoryBean对象的情况,如果不是FactoryBean会直接返回beanInstance实例

(4)BeanFactoryUtils.isFactoryDereference(name)
判断name是否以“&”为前缀

(5)name 以“&”为前缀直接返回入参中的 MyFactoryBean 对象


User bean = (User) ac.getBean(“myFactoryBean”) 执行流程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


与上述1-4步逻辑相同

(5)getObjectFromFactoryBean(factory, beanName, !synthetic);
获取一个对象以从给定的FactoryBean中公开
(6)doGetObjectFromFactoryBean(factory, beanName);
获取factory管理的对象实例
(7)factory.getObject();
调用子类的具体实现

整体脉络

在这里插入图片描述

关键源码

getObjectForBeanInstance()

protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

		// Don't let calling code try to dereference the factory if the bean isn't a factory.
		// 如果Bean不是工厂,不要让调用代码尝试取消对工厂的引用
		// 如果name为FactoryBean的解引用.name是以'&'开头,就是FactoryBean的解引用
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			// 如果beanInstance是NullBean实例
			if (beanInstance instanceof NullBean) {
				// 返回beanInstance
				return beanInstance;
			}
			// 如果beanInstance不是FactoryBean实例
			if (!(beanInstance instanceof FactoryBean)) {
				// 抛出Bean不是一个Factory异常
				throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
			}
			// 如果mbd不为null
			if (mbd != null) {
				// 设置mbd是否是FactoryBean标记为true
				mbd.isFactoryBean = true;
			}
			// 返回beanInstance
			return beanInstance;
		}

		// Now we have the bean instance, which may be a normal bean or a FactoryBean.
		// If it's a FactoryBean, we use it to create a bean instance, unless the
		// caller actually wants a reference to the factory.
		// 现在我们有了Bean实例,他可能是一个普通的Bean或FactoryBean。
		// 如果它是FactoryBean,我们使用它来创建一个Bean实例,除非调用者确实需要对工厂的引用。
		// 如果beanInstance不是FactoryBean实例
		if (!(beanInstance instanceof FactoryBean)) {
			return beanInstance;
		}

		// 定义为bean公开的对象,初始化为null
		Object object = null;
		// 如果mbd不为null
		if (mbd != null) {
			// 更新mbd的是否是FactoryBean标记为true
			mbd.isFactoryBean = true;
		}
		else {
			// 从FactoryBean获得的对象缓存集中获取beanName对应的Bean对象
			object = getCachedObjectForFactoryBean(beanName);
		}
		// 如果object为null
		if (object == null) {
			// Return bean instance from factory.
			// 从工厂返回Bean实例
			// 将beanInstance强转为FactoryBean对象
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			// Caches object obtained from FactoryBean if it is a singleton.
			// 如果是单例对象,则缓存从FactoryBean获得的对象、
			// 如果mbd为null&&该BeanFactory包含beanName的BeanDefinition对象。
			if (mbd == null && containsBeanDefinition(beanName)) {
				//获取beanName合并后的本地RootBeanDefintiond对象
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			// 是否是'synthetic'标记:mbd不为null && 返回此bean定义是否是"synthetic"【一般是指只有AOP相关的prointCut配置或者
			// Advice配置才会将 synthetic设置为true】
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			// 从BeanFactory对象中获取管理的对象.如果不是synthetic会对其对象进行该工厂的后置处理
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		// 返回为bean公开的对象
		return object;
	}

getObjectFromFactoryBean()

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
		// 如果factory管理的对象是单例且beanName已经在该BeanFactory的单例对象的高速缓存Map集合DefaultListableBeanFactory.singletonObjects中
		if (factory.isSingleton() && containsSingleton(beanName)) {
			// 获取单例互斥体(一般使用singletonObjects)进行加锁,来保证线程安全
			synchronized (getSingletonMutex()) {
				// 获取beanName的Bean对象
				Object object = this.factoryBeanObjectCache.get(beanName);
				// 如果object为null
				if (object == null) {
					// 获取factory管理的对象实例并赋值给object
					object = doGetObjectFromFactoryBean(factory, beanName);
					// Only post-process and store if not put there already during getObject() call above
					// (e.g. because of circular reference processing triggered by custom getBean calls)
					// 仅在上面的getObject()调用期间进行后处理和存储(如果尚未放置)
					// (例如,由于自定义getBean调用触发的循环引用处理)
					// 重新从factoryBeanObjectCache中获取beanName对应bean对象
					Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
					// 如果bean对象不为null
					if (alreadyThere != null) {
						// 让object引用alreadyThere
						object = alreadyThere;
					}
					else {
						// 如果要进行后处理
						if (shouldPostProcess) {
							// 如果beanName当前正在创建(在整个工厂内)
							if (isSingletonCurrentlyInCreation(beanName)) {
								// Temporarily return non-post-processed object, not storing it yet..
								// 暂时返回未处理的对象,尚未存储
								// 直接返回object
								return object;
							}
							// 创建单例之前的回调
							beforeSingletonCreation(beanName);
							try {
								// 对从FactoryBean获得的给定对象进行后处理.
								object = postProcessObjectFromFactoryBean(object, beanName);
							}
							// 捕捉所有在进行后处理的抛出的异常
							catch (Throwable ex) {
								// 抛出Bean创建异常:FactoryBean的单例对象的后处理失败
								throw new BeanCreationException(beanName,
										"Post-processing of FactoryBean's singleton object failed", ex);
							}
							finally {
								// 创建单例后的回调
								afterSingletonCreation(beanName);
							}
						}
						// beanName已经在该BeanFactory的单例对象的高速缓存Map集合DefaultListableBeanFactory.singletonObjects中
						if (containsSingleton(beanName)) {
							// 将beanName以及object添加到factoryBeanObjectCache中
							this.factoryBeanObjectCache.put(beanName, object);
						}
					}
				}
				// 返回factory管理的对象实例(该对象已经过工厂的后处理)
				return object;
			}
		}
		else {
			// 获取factory管理的对象实例
			Object object = doGetObjectFromFactoryBean(factory, beanName);
			// 如果要进行后处理
			if (shouldPostProcess) {
				try {
					// 对从FactoryBean获得的给定对象进行后处理
					object = postProcessObjectFromFactoryBean(object, beanName);
				}
				// 捕捉所有在进行后处理的抛出的异常
				catch (Throwable ex) {
					// 抛出Bean创建异常:FactoryBean的单例对象的后处理失败
					throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
				}
			}
			// 返回factory管理的对象实例(该对象已经过工厂的后处理)
			return object;
		}
	}

doGetObjectFromFactoryBean()

private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
		// 定义一个用于保存factory管理的对象实例的变量
		Object object;
		try {
			// 如果有安全管理器
			if (System.getSecurityManager() != null) {
				// 获取访问控制的上下文对象
				AccessControlContext acc = getAccessControlContext();
				try {
					// 以特权方式运行来获取factory管理的对象实例赋值给object
					object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
				// 获取factory管理的对象实例赋值给object
				object = factory.getObject();
			}
		}
		catch (FactoryBeanNotInitializedException ex) {
			throw new BeanCurrentlyInCreationException(beanName, ex.toString());
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
		}

		// Do not accept a null value for a FactoryBean that's not fully
		// initialized yet: Many FactoryBeans just return null then.
		// 不接受尚未完全初始化的FactoryBean的null值:然后,许多FactoryBeans仅返回null
		// 如果object为null
		if (object == null) {
			// 如果 beanName当前正在创建(在整个工厂内)
			if (isSingletonCurrentlyInCreation(beanName)) {
				// 抛出当前正在创建Bean异常:当前正在创建的FactoryBean从getObject返回null
				throw new BeanCurrentlyInCreationException(
						beanName, "FactoryBean which is currently in creation returned null from getObject");
			}
			// 让object引用一个新的NullBean实例
			object = new NullBean();
		}
		// 返回factory管理的对象实例object
		return object;
	}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小刘说

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值