FactoryBean接口简述
BeanFactory与FactoryBean接口,相信很多刚翻看Spring源码跟我一样很好奇这俩货怎么长得这么像,分别都是干啥用的。BeanFactory是Spring中Bean工厂的顶层接口,也是我们常说的SpringIOC容器,它定下了IOC容器的一些规范和常用方法并管理着Spring中所有的Bean,今天我们不讲它,我们看一下后面那个FactoryBean
public interface FactoryBean {
@Nullable
T getObject() throws Exception;
@Nullable
Class> getObjectType();
default boolean isSingleton() {
return true;
}
}
先说下FactoryBean和其作用再开始分析:首先它是一个Bean,但又不仅仅是一个Bean。它是一个能生产或修饰对象生成的工厂Bean,类似于设计模式中的工厂模式和装饰器模式。它能在需要的时候生产一个对象,且不仅仅限于它自身,它能返回任何Bean的实例
FactoryBean在Spring中的应用
在Spring中我们的Bean都会被Spring的IOC容器所管理,在AbstractApplicationContext中有一个很重要的方法:refresh(),项目启动或重启的时候refresh()会调用getBean()初始化所有的Bean,这个getBean()最终会指向AbstractBeanFactory中的getBean()方法。上述方法的调用链过长,我们不过多赘述,详细的getBean()源码在这里
在AbstractBeanFactory抽象类中,不管是根据名称还是根据类型,getBean()方法最终都会调用doGetBean()方法
在doGetBean()方法中一开始就获取了名称beanName和实例sharedInstance
@SuppressWarnings('unchecked')
protected T doGetBean(final String name, @Nullable final Class requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// 方法解释如下图
Object sharedInstance = getSingleton(beanName);
// 如果已经初始化过,直接从缓存中获取
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug('Returning eagerly cached instance of singleton bean '' + beanName +
'' that is not fully initialized yet - a consequence of a circular reference');
}
else {
logger.debug('Returning cached instance of singleton bean '' + beanName + ''');
}
}
// 如果 sharedInstance 是普通的单例 bean,下面的方法会直接返回。但如果
// 是 FactoryBean 类型的,则需调用 getObject 工厂方法获取真正的 bean 实例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 如果是原型不应该在初始化的时候创建,在这里直接抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 将别名解析成真正的beanName
String nameToLookup = originalBeanName(name);
// 如果parentBeanFactory存在,并且beanName在当前BeanFactory不存在Bean定义,则尝试从parentBeanFactory中获取bean实例
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
// 尝试在parentBeanFactory中获取bean对象实例
else if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
// 根据beanName重新获取MergedBeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
// 遍历当前bean依赖的bean名称集合
for (String dep : dependsOn) {
// 检查dep是否依赖于beanName,即检查是否存在循环依赖
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
'Circular depends-on relationship between '' + beanName + '' and '' + dep + ''');
}
// 将dep和beanName的依赖关系注册到缓存中
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
''' + beanName + '' depends on missing bean '' + dep + ''', ex);
}
}
}
// scope为 singleton 的bean创建
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
// 创建Bean实例
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
// 返回beanName对应的实例对象
// 这里主要处理实现了FactoryBean的情况,需要调用重写的getObject()方法来获取实际的Bean实例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// scope为 prototype 的bean创建
else if (mbd.isPrototype()) {
Object prototypeInstance = null;
try {
// 创建实例前的操作(将beanName保存到prototypesCurrentlyInCreation缓存中)
beforePrototypeCreation(beanName);
// 创建Bean实例
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
// 创建实例后的操作(将创建完的beanName从prototypesCurrentlyInCreation缓存中移除)
afterPrototypeCreation(beanName);
}
// 返回beanName对应的实例对象
// 这里主要处理实现了FactoryBean的情况,需要调用重写的getObject()方法来获取实际的Bean实例
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
// 既不是单例也不是原型的 bean创建,可能是 request之类的
// 根据scopeName,从缓存拿到scope实例
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException('No Scope registered for scope name '' + scopeName + ''');
}
try {
// 既不是单例也不是原型的bean创建
Object scopedInstance = scope.get(beanName, () -> {
// 创建实例前的操作(将beanName保存到prototypesCurrentlyInCreation缓存中)
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
// 创建实例后的操作(将创建完的beanName从prototypesCurrentlyInCreation缓存中移除)
afterPrototypeCreation(beanName);
}
});
// 返回beanName对应的实例对象
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
'Scope '' + scopeName + '' is not active for the current thread; consider ' +
'defining a scoped proxy for this bean if you intend to refer to it from a singleton',
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// ...... 省略
return (T) bean;
}
transformedBeanName()是为了获取bean真正的名称,它会去掉name前面的&而getSingleton()是从父类DefaultSingletonBeanRegistry的getSingleton()方法中的singletonObjects一级缓存中取的这个bean的实例
回到doGetBean()方法中,拿到sharedInstance后,后面的一大堆操作做了单例、多例等判断,最终会走到getObjectForBeanInstance(),关键部分就在这个方法中,进入方法代码
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// 如果 name 不为空且以 & 开头
if (BeanFactoryUtils.isFactoryDereference(name)) {
// beanInstance 属于 NullBean 或其子类的实例
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
}
// beanInstance 不是属于 FactoryBean 或其子类的实例,或 name 不为空且以 & 开头
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
// 只有当 name 不为空且以 & 开头,并且 beanInstance 属于 FactoryBean 或其子类的实例时,才会执行下面
Object object = null;
if (mbd == null) {
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
FactoryBean> factory = (FactoryBean>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
// 关键部分,如下
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
protected Object getObjectFromFactoryBean(FactoryBean> factory, String beanName, boolean shouldPostProcess) {
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
// 关键部分
object = doGetObjectFromFactoryBean(factory, beanName);
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (shouldPostProcess) {
if (isSingletonCurrentlyInCreation(beanName)) {
return object;
}
beforeSingletonCreation(beanName);
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
'Post-processing of FactoryBean's singleton object failed', ex);
}
finally {
afterSingletonCreation(beanName);
}
}
if (containsSingleton(beanName)) {
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
else {
// 关键部分
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, 'Post-processing of FactoryBean's object failed', ex);
}
}
return object;
}
}
private Object doGetObjectFromFactoryBean(final FactoryBean> factory, final String beanName)
throws BeanCreationException {
Object object;
try {
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged((PrivilegedExceptionAction
关键代码object=factory.getObject()这个factory就是我们传入的beanInstance实例。绕了这么一大圈,getBean()方法返回的居然是我们实现FactoryBean接口定义的getObject()方法
总结
FactoryBean接口的作用
一般情况下,Spring通过反射机制利用的class属性指定实现类实例化Bean,在某些情况下,实例化Bean过程比较复杂,如果按照传统的方式,则需要在中提供大量的配置信息。配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。Spring为此提供了一个orspringframeworbeafactory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑。FactoryBean接口对于Spring框架来说占用重要的地位,Spring自身就提供了70多个FactoryBean的实现。它们隐藏了实例化一些复杂Bean的细节,给上层应用带来了便利
FactoryBean是一个能生产或修饰对象生成的工厂Bean。一个Bean如果实现了FactoryBean接口,那么根据该Bean的名称获取到的实际上是getObject()返回的对象,而不是这个Bean自身实例,如果要获取这个Bean自身实例,那么需要在名称前面加上&符号
测试验证
下面通过代码测试验证上面的流程,先定义一个Bean实现FactoryBean接口
@Component
public class MyBean implements FactoryBean {
private String message;
public MyBean() {
this.message = '通过构造方法初始化实例';
}
@Override
public Object getObject() throws Exception {
MyBean myBean = new MyBean();
myBean.message = '通过FactoryBean.getObject()创建实例';
// 这里并不一定要返回MyBean自身的实例,可以是其他任何对象的实例
return myBean;
}
@Override
public Class> getObjectType() {
return MyBean.class;
}
public String getMessage() {
return message;
}
}
MyBean实现了FactoryBean接口的两个方法,getObject()是可以返回任何对象的实例的,这里测试就返回MyBean自身实例,且返回前给message字段赋值。同时在构造方法中也为message赋值。然后测试代码中先通过名称获取Bean实例,打印message的内容,再通过&+名称获取实例并打印message内容
结果如下
myBean1 = 通过FactoryBean.getObject()初始化实例
myBean2 = 通过构造方法初始化实例
myBean1.equals(myBean2) = false
文章为作者独立观点,不代表 股票程序化软件自动交易接口观点
james2023-05-24
没人逼你买,是大家抢着买,股票就算定个500发行价,照样被疯抢,那为什么不高价发行呢?