FactoryBean

友情提示:如果时间紧,任务重,可以直接查看页面最后的总结。

 

一提到FactoryBean,大家可能会立马想到BeanFactory,这两个单词已经被我混淆了不知多少次,总是记不住谁是谁的谁,这里其实就记住他们的最后一个单词去区分他们就好了(Bean、Factory),那么为了让大家对这两个概念有更清楚的了解,我们就来说一下他们两个之间的区别

从他们的尾部单词可知,FactoryBean是一个Bean,而BeanFactory是我们所说的容器,具有管理Bean的功能,前面我们已经讲述过BeanFactory相关的功能,这里我们不在过多的赘述,他俩的直观区别就是一个是bean,一个是管理bean的容器

FactoryBean是一种特殊的Bean,FactoryBean接口定义了三个方法

public interface FactoryBean<T> {
​
   String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
   
   @Nullable
    //返回有FactoryBean创建的Bean实例,如果isSingleton()返回true,则该实例会放到Spring容器的单实例缓存池中。 
   T getObject() throws Exception;
   
   @Nullable
    //返回FactoryBean创建Bean的类型。 
   Class<?> getObjectType();
​
    //确定由FactoryBean创建Bean的作用域是singleton还是prototype. 
   default boolean isSingleton() {
      return true;
   }
}

 

一般,我们都会通过实现Spring内部中的FactoryBean接口去创建一个自定义的factorybean

@Component
public class FactoryBeanTest implements FactoryBean {
    @Override
    public Object getObject() throws Exception {
        return new ObjectBean();
    }
​
    @Override
    public Class<?> getObjectType() {
        return ObjectBean.class;
    }
}
package com.beans;
​
public class ObjectBean {
}
 

然后再在配置类中去获取在getObject()方法中生成的ObjectBean对象

@ComponentScan("com.beans")
public class mainT {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(mainT.class);
        System.out.println(context.getBean("factoryBeanTest"));
        System.out.println(context.getBean("factoryBeanTest"));
        System.out.println(context.getBean("factoryBeanTest"));
        //System.out.println(context.getBean("&factoryBeanTest"));
        }
}

 

在这里提出一个疑问:上述获得的三个Bean是否是同一个?

答案 : 是同一个 ,因为FactoryBean中有一个默认的方法,是否是单例,默认为true,如果想得到非单例,可以重写这个默认方法

default boolean isSingleton() {
      return true;
   }

 

即默认是单例的。

在提出一个疑问?上述4个Bean得到的是否是同一个类

答案:不是

System.out.println(context.getBean("factoryBeanTest"));
System.out.println(context.getBean("factoryBeanTest"));
System.out.println(context.getBean("factoryBeanTest"));
//com.beans.ObjectBean@77f80c04
//com.beans.ObjectBean@77f80c04
//com.beans.ObjectBean@77f80c04
System.out.println(context.getBean("&factoryBeanTest"));
//com.beans.FactoryBeanTest@1dac5ef

 

上面的注释是每一个输出语句输出的结果,可以发现上方三个beanName没有加&号的得到的bean是在FactoryBean中getObject方法new的类,而加了&符号的得到的是FactoryBean自身。

所以当你需要得到FactoryBean自身的话,在getBean的时候要在BeanName前加上一个或多个&即可。

那么Spring如何去处理这个名字呢,我们可以看一下Spring中的源码

//返回BeanName,去掉FatoryBean的&前缀,并且把name当作别名去aliasMap中寻找原始的beanName
protected String transformedBeanName(String name) {
    return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
public static String transformedBeanName(String name) {
    Assert.notNull(name, "'name' must not be null");
    if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
        return name;
    }
    //如果BeanName以&开头,截取&后的beanname,并且把截取前后的name存储到transformedBeanNameCache中
    return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
        do {
            beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
        }
        while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
        return beanName;
    });
}

 

 
public String canonicalName(String name) {
    String canonicalName = name;
    // Handle aliasing...
    String resolvedName;
    do {
        //去找原始beanName,aliasMap:{别名:原始名}
        resolvedName = this.aliasMap.get(canonicalName);
        if (resolvedName != null) {
            canonicalName = resolvedName;
        }
    }
    while (resolvedName != null);
    //如果通过别名找到原始beanName,则返回找出的原始beanName,如果没有找到,则返回传进来的BeanName
    return canonicalName;
}

 

上述就是Spring处理这个beanName的方法,如果对上面代码有疑问或者不接,可以看作者做得一个流程图,来帮助您加深记忆,更容易理解

 

这里要说一下,Spring在getbean之前也就是在启动的时候就会把FactoryBeanTest都加载到的BeanFactory中的单例池中,但没有加载ObjectBean。

那么除了FactoryBean以外还可以通过什么来new一个对象而得到一个bean呢

就是@Bean注解,如下面例子所示:

@Configuration
public class mainConfiguration {
​
    @Bean
    public ObjectBean getObjectBean(){
        return new ObjectBean();
    }
​
}

 

那么可以通过@Bean注解以一个相同的方法来得到一个Bean,为什么还需要FactoryBean来定义一个Bean呢?因为当一个类继承了FactoryBean之后,它还可以继承其他的类和接口,起到一个拓展的作用。

public class FactoryBeanTest implements FactoryBean, BeanFactoryPostProcessor...

 

那么在getBean方法中是如何去判断这个Bean是不是一个FactoryBean以及如何加载getObject()方法中取到得对象为bean得呢

我们一同来看一下getBean()方法的源码,只需要看前半部分即可

protected <T> T doGetBean(
            String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
            throws BeansException {
        //返回BeanName,去掉FatoryBean的&前缀,并且把name当作别名去aliasMap中寻找原始的beanName
        String beanName = transformedBeanName(name);
        Object beanInstance;
​
        // 根据beanName从单例池中获取bean
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            if (logger.isTraceEnabled()) {
                if (isSingletonCurrentlyInCreation(beanName)) {
                    logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                            "' that is not fully initialized yet - a consequence of a circular reference");
                }
                else {
                    logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
            //判断sharedInstance是不是FactoryBean
            beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }
​
//      else {
//          // Fail if we're already creating this bean instance:
//          // We're assumably within a circular reference.
//          if (isPrototypeCurrentlyInCreation(beanName)) {
//              throw new BeanCurrentlyInCreationException(beanName);
//          }
//
//          // Check if bean definition exists in this factory.
//          BeanFactory parentBeanFactory = getParentBeanFactory();
//          if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
//              // Not found -> check parent.
//              String nameToLookup = originalBeanName(name);
//              if (parentBeanFactory instanceof AbstractBeanFactory) {
//                  return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
//                          nameToLookup, requiredType, args, typeCheckOnly);
//              }
//              else if (args != null) {
//                  // Delegation to parent with explicit args.
//                  return (T) parentBeanFactory.getBean(nameToLookup, args);
//              }
//              else if (requiredType != null) {
//                  // No args -> delegate to standard getBean method.
//                  return parentBeanFactory.getBean(nameToLookup, requiredType);
//              }
//              else {
//                  return (T) parentBeanFactory.getBean(nameToLookup);
//              }
//          }
//            //父子容器都没有才去创建
//          if (!typeCheckOnly) {
//              markBeanAsCreated(beanName);
//          }
//
//          StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
//                  .tag("beanName", name);
//          try {
//              if (requiredType != null) {
//                  beanCreation.tag("beanType", requiredType::toString);
//              }
//              RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
//              checkMergedBeanDefinition(mbd, beanName, args);
//
//              // Guarantee initialization of beans that the current bean depends on.
//              String[] dependsOn = mbd.getDependsOn();
//              if (dependsOn != null) {
//                  for (String dep : dependsOn) {
//                      //判断beanName是不是也被dep依赖了,如果是,就是相互依赖
//                      if (isDependent(beanName, dep)) {
//                          throw new BeanCreationException(mbd.getResourceDescription(), beanName,
//                                  "Circular depends-on relationship between '" + beanName + "' and '" + //dep + "'");
//                      }
//                      //加载依赖的bean
//                      //存在在两个map中
//                      //1、dependentBeanMap ,key为dep,value是一个LinkedHashSet,表示dep被哪些bean依赖了
//                      //2、dependenciesForBeanMap key为beanName,value是一个LinkedHashSet,表示beanName依赖了哪些bean
//                      registerDependentBean(dep, beanName);
//                      try {
//    //先去生成所依赖的bean
//    getBean(dep);
//    }
//    catch (NoSuchBeanDefinitionException ex) {
//    throw new BeanCreationException(mbd.getResourceDescription(), beanName,
//    "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
//    }
//    }
//    }
//
//    // Create bean instance.
//    if (mbd.isSingleton()) {
//    sharedInstance = getSingleton(beanName, () -> {
//    try {
//    return createBean(beanName, mbd, args);
//    }
//    catch (BeansException ex) {
//    // Explicitly remove instance from singleton cache: It might have been put there
//    // eagerly by the creation process, to allow for circular reference resolution.
//    // Also remove any beans that received a temporary reference to the bean.
//    destroySingleton(beanName);
//    throw ex;
//    }
//    });
//    //sharedInstance可能是一个FactoryBean,所以需要单独再去factoryBeanObjectCache中去获取对应的对象
//    beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
//    }
//
//    else if (mbd.isPrototype()) {
//    // It's a prototype -> create a new instance.
//    Object prototypeInstance = null;
//    try {
//    beforePrototypeCreation(beanName);
//    prototypeInstance = createBean(beanName, mbd, args);
//    }
//    finally {
//    afterPrototypeCreation(beanName);
//    }
//    beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
//    }
//                //其他的scope request,session
//    else {
//    String scopeName = mbd.getScope();
//    if (!StringUtils.hasLength(scopeName)) {
//    throw new IllegalStateException("No scope name defined for bean ´" + beanName + //"'");
//    }
//    Scope scope = this.scopes.get(scopeName);
//    if (scope == null) {
//    throw new IllegalStateException("No Scope registered for scope name '" + scopeName + //"'");
//    }
//    try {
//    Object scopedInstance = scope.get(beanName, () -> {
//    beforePrototypeCreation(beanName);
//    try {
//    return createBean(beanName, mbd, args);
//    }
//    finally {
//    afterPrototypeCreation(beanName);
//    }
//    });
//    beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
//    }
//    catch (IllegalStateException ex) {
//    throw new ScopeNotActiveException(beanName, scopeName, ex);
//    }
//    }
//    }
//    catch (BeansException ex) {
//    beanCreation.tag("exception", ex.getClass().toString());
//    beanCreation.tag("message", String.valueOf(ex.getMessage()));
//    cleanupAfterBeanCreationFailure(beanName);
//    throw ex;
//    }
//    finally {
//    beanCreation.end();
//    }
//    }
//
//    return adaptBeanInstance(name, beanInstance, requiredType);
//  }

 

/**
* @param beanInstance 从单例池中获取到的bean
* @param name  原始name(没有经过任何处理,比如,没有去掉&符号)
* @param beanName  经过转换后的name(例如:去掉了&符号)
* @param mbd null
* @return
*/
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.
        //如果是&FactoryBean,那么直接返回单例池中的对象,这里就是判断原始name中是否以&符号开头
        if (BeanFactoryUtils.isFactoryDereference(name)) {
            if (beanInstance instanceof NullBean) {
                return beanInstance;
            }
            if (!(beanInstance instanceof FactoryBean)) {
                throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
            }
            if (mbd != null) {
                mbd.isFactoryBean = true;
            }
            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没有继承FactoryBean且beanName没有以&开头,则认为是普通bean,直接返回
        if (!(beanInstance instanceof FactoryBean)) {
            return beanInstance;
        }
        // 如果beanInstance是FactoryBean且BeanName是以&开头的
        Object object = null;
        if (mbd != null) {
            mbd.isFactoryBean = true;
        }
        else {
            //首先去缓存中通过BeanName获取getObject方法得到的bean(这是为单例准备的)
            object = getCachedObjectForFactoryBean(beanName);
        }
        //从factoryBeanObjectCache中没有拿到则进行创建
        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)) {
                //获取合并后beanDefinition
                mbd = getMergedLocalBeanDefinition(beanName);
            }
            boolean synthetic = (mbd != null && mbd.isSynthetic());
            //调用getObject方法得到对象并放入factoryBeanObjectCache中
            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) {
                    //调用getObject方法得到一个对象
                    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)
                    Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                    if (alreadyThere != null) {
                        object = alreadyThere;
                    }
                    else {
                        if (shouldPostProcess) {
                            //单例正在创建
                            if (isSingletonCurrentlyInCreation(beanName)) {
                                // Temporarily return non-post-processed object, not storing it yet..
                                return object;
                            }
                            beforeSingletonCreation(beanName);
                            try {
                                //调用BeanPostProcessor执行初始化后的逻辑,主要就是进行AOP
                                object = postProcessObjectFromFactoryBean(object, beanName);
                            }
                            catch (Throwable ex) {
                                throw new BeanCreationException(beanName,
                                        "Post-processing of FactoryBean's singleton object failed", ex);
                            }
                            finally {
                                afterSingletonCreation(beanName);
                            }
                        }
                        //如果是单例的,存入factoryBeanObjectCache中 
                        //{工厂bean的名(没有&符号):getObject()方法中new的新对象}
                        if (containsSingleton(beanName)) {
                            this.factoryBeanObjectCache.put(beanName, object);
                        }
                    }
                }
                return object;
            }
        }
        //当FactoryBean不是单例的情况下
        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;
        }
    }

 

下面是一个流程图,帮您加深印象以及能够更好得了解上面得过程

 

总结:

1、什么是FactoryBean

FactoryBean本质上是一个Bean,但他是一个特殊的Bean,而是一个能够生产和修饰对象生成的工厂Bean。

2、FactoryBean与BeanFactory的区别

如1所说,FactoryBean本质上是一个Bean,但他比较特殊,它是可以生产和修饰对象生成的工厂Bean。

BeanFactory本质上是一个容器,所有Bean都是由BeanFactory来管理的,BeanFactory是一个接口,提供了IOC容器应遵守的最基本的接口,他的核心实现类是DefaultListableBeanFactory。

3、FactoryBean生产的Bean默认是单例的还是多例的

默认是单例的,可以重写它的isSingleton()方法,修改返回值为false即可变为多例

4、如何获得FactoryBean本身这个Bean

可以通过在beanName前加上一个或多个&符号来获取

例如:getBean("&FactoryBean的名字")

 

posted @ 2021-10-23 15:45  萨科拉  阅读(449)  评论(0编辑  收藏  举报