FactoryBean

什么是FactoryBean

FactoryBean不是BeanFactory,它是一个特殊的Bean。

我们可以写自己的XXXBeanFactory来实现BeanFactory接口,并重写其中的方法:

  1. package com.example.firstspringboot.service;
  2. import org.springframework.beans.factory.FactoryBean;
  3. import org.springframework.stereotype.Component;
  4. @Component
  5. public class LangFactoryBean implements FactoryBean {
  6. @Override
  7. public Object getObject() throws Exception {
  8. return new Person();
  9. }
  10. @Override
  11. public Class<?> getObjectType() {
  12. return Person.class;
  13. }
  14. @Override
  15. public boolean isSingleton() {
  16. return FactoryBean.super.isSingleton();
  17. }
  18. }
  1. public class FirstSpringBootApplication {
  2. public static void main(String[] args) {
  3. ApplicationContext applicationContext = SpringApplication.run(FirstSpringBootApplication.class, args);
  4. System.out.println(applicationContext.getBean("langFactoryBean"));
  5. }
  6. }

如上代码,当我们使用getBean方法来获取langFactoryBean时,得到的对象不是langFactoryBean,而是LangFactoryBean中重写的getObject()方法中返回的对象。

此外,并不是每次调用getBean方法,都调用一次getObject()方法,实际上getObject方法只会调用一次。

那么如果我们就是想取到langFactoryBean这个Bean,怎么办呢?

加上&

  1. applicationContext.getBean("&langFactoryBean")

原理:

  1. 在doGetBean方法中调用了getObjectForBeanInstance方法: ```java protected T doGetBean(String name, @Nullable Class requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException { …; beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null); …; }
  1. 2. getObjectForBeanInstance中调用了BeanFactoryUtils.isFactoryDereference(name), 判断是不是以`&`开头:
  2. ```java
  3. protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
  4. if (BeanFactoryUtils.isFactoryDereference(name)) {
  5. ...;
  6. reutrn beanInstance;
  7. }
  8. }
  9. public static boolean isFactoryDereference(@Nullable String name) {
  10. return name != null && name.startsWith("&");
  11. }
  1. 因此,以&开头就认为是个FactoryBean,getBean 的时候加了&就直接返回这个FactoryBean。
  2. 如果是以&开头,但是不是一个FactoryBean(说明是普通Bean),那么也直接返回这个Bean(即便以&开头);

    else if (!(beanInstance instanceof FactoryBean)) {
     return beanInstance;
    }
    
  3. 否则,那就说明是一个FactoryBean,而且调用getBean的时候没有以&开头,就回去尝试从factoryBeanObjectCache中获取缓存的Bean,因为第一次调用的时候这个Bean并没有初始化,因此得到的是Null ```java object = this.getCachedObjectForFactoryBean(beanName);

protected Object getCachedObjectForFactoryBean(String beanName) { return this.factoryBeanObjectCache.get(beanName); }


6. 如果得到的是NULL, 就会去尝试调用BeanFactory中的getObject方法,创建这个Bean;
```java
if (object == null) {
    ...;
    object = this.getObjectFromFactoryBean(factory, beanName, !synthetic);
}

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
    if (factory.isSingleton() && this.containsSingleton(beanName)) {
        ...;
        object = this.doGetObjectFromFactoryBean(factory, beanName);
    }
}

private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
    if (System.getSecurityManager() != null) {
        ...;
    } else {
        object = factory.getObject();
    }
}
  1. 拿到这个对象以后,放入到factoryBeanObjectCache缓存中去(不会放到单例池中):
    if (this.containsSingleton(beanName)) {
     this.factoryBeanObjectCache.put(beanName, object);
    }
    

FactoryBean有什么用

可以用来集成第三方库,例如Mybatis。如果我们要将UserMapper注入到UserService里边去,因为UserMapper是个接口,所以需要注入的是UserMapper的代理对象,而且这个代理对象还需要是Spring中的一个Bean。

此时就可以通过FactoryBean来生成该UserMapper的代理对象。

BeanFactory和FactoryBean的区别

BeanFactory是整个Spring中最重要的东西,主要的职责就是创建各种各样的Bean。

FactoryBean是一种特殊的Bean,这个FactoryBean内部可以创建一个新的Bean。

GetBean

GetBean方法干了两件事:

  • 获取Bean;
  • 如果Bean不存在,去生成Bean;

获取Bean

GetBean调用doGetBean方法,实际操作都是在doGetBean中。

doGetBean方法首先去单例池里获取Bean, 如果找到了并不是直接返回这个Bean, 因为这个Bean可能是FactoryBean,因此要通过调用getObjectForBeanInstance方法来获得真正想要的Bean.

protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
    xxx;
    Object sharedInstance = this.getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
    }
}

getObjectForBeanInstance方法:

  • 如果是普通Bean,返回普通Bean对象;
  • 如果是FactoryBean

    • 如果加了&开头,则返回FactoryBean对象;
    • 否则返回FactoryBean中getObject方法里返回的对象。

      protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
         // 如果以&开头
         if (BeanFactoryUtils.isFactoryDereference(name)) {
             // 如果是NullBean,直接返回
             if (beanInstance instanceof NullBean) {
                 return beanInstance;
             // 如果不是FactoryBean对象,抛出异常
             } else if (!(beanInstance instanceof FactoryBean)) {
                 throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
      
             // 说明确实是FactoryBean,因为加了&,所以就返回这个FactoryBean对象
             } else {
                 if (mbd != null) {
                     mbd.isFactoryBean = true;
                 }
      
                 return beanInstance;
             }
         // 如果没有以&开头并且不是FactoryBean
         // 说明是普通Bean,返回这个BeanInstance
         } else if (!(beanInstance instanceof FactoryBean)) {
             return beanInstance;
      
         // 否则就是FactoryBean,并且没有以&开头
         } else {
             Object object = null;
             if (mbd != null) {
                 mbd.isFactoryBean = true;
             } else {
                 // 尝试去FactoryBeanCache中获取getObject中返回的对象
                 object = this.getCachedObjectForFactoryBean(beanName);
             }
      
             // 如果该对象不存在,尝试通过FactoryBean中的getObject方法来获取对象。
             if (object == null) {
                 FactoryBean<?> factory = (FactoryBean)beanInstance;
                 if (mbd == null && this.containsBeanDefinition(beanName)) {
                     mbd = this.getMergedLocalBeanDefinition(beanName);
                 }
      
                 boolean synthetic = mbd != null && mbd.isSynthetic();
                 // 该方法就是去通过FactoryBean中的getObject方法来获取Bean
                 object = this.getObjectFromFactoryBean(factory, beanName, !synthetic);
             }
      
             return object;
         }
      }
      

      如果在单例池中没有找到Bean,且本BeanFactory中找不到对应BeanName的BeanDefinition,但是该BeanFactory存在parentBeanFactory,就尝试去parentBeanFactory中去查找。

      BeanFactory parentBeanFactory = this.getParentBeanFactory();
      if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
      String nameToLookup = this.originalBeanName(name);
      if (parentBeanFactory instanceof AbstractBeanFactory) {
         return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
      }
      
      if (args != null) {
         return parentBeanFactory.getBean(nameToLookup, args);
      }
      
      if (requiredType != null) {
         return parentBeanFactory.getBean(nameToLookup, requiredType);
      }
      
      return parentBeanFactory.getBean(nameToLookup);
      }
      

生成Bean

经过上述两个步骤以后,说明单例池中确实没有我们想要的Bean,FactoryBean缓存中也没有,parentBeanFactory中也没有,那就确实没有这个Bean。

因此我们要去生成Bean。

生成Bean之前,首先要去获得MergedBeanDefinition。

RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);

然后先去生成那些依赖的Bean,如果发现有循环依赖需要抛出异常。

String[] dependsOn = mbd.getDependsOn();
String[] var12;

if (dependsOn != null) {
    var12 = dependsOn;
    int var13 = dependsOn.length;

    for(int var14 = 0; var14 < var13; ++var14) {
        String dep = var12[var14];
        // 检查是否存在循环依赖
           // 如果有循环依赖就要抛出异常
        if (this.isDependent(beanName, dep)) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
        }

        this.registerDependentBean(dep, beanName);

        try {
            this.getBean(dep);
        } catch (NoSuchBeanDefinitionException var31) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var31);
        }
    }
}

在生成完了依赖的那些Bean以后,就尝试去生成自己的这个Bean了。根据不同Bean的Scope来进行不同的实例化过程(singleton, prototype, request,Session…)

以下生命周期将详细解释Bean的生成过程

加载类

首先根据mergedBeanDefinition和beanName来尝试加载类:

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
    xxx;
    Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
    xxx;
}

在进行mergedBeanDefinition的解析的过程中,里边有个属性是BeanClass,可能是字符串(类的全限定名com.lang.xxx),可能是一个解析好的Class对象。

如果已经是一个Class对象了,那么就直接返回:

protected Class<?> resolveBeanClass(RootBeanDefinition mbd, String beanName, Class<?>... typesToMatch) throws CannotLoadBeanClassException {
    xxx;
    if (mbd.hasBeanClass()) {
        return mbd.getBeanClass();
    }
    xxx;

}

否则就调用doResolveBeanClass方法,获得类加载器,尝试去加载类。

private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch) throws ClassNotFoundException {
    ClassLoader beanClassLoader = this.getBeanClassLoader();
    ClassLoader dynamicLoader = beanClassLoader;
    xxx;

    return mbd.resolveBeanClass(beanClassLoader);
}
                      ↓
public Class<?> resolveBeanClass(@Nullable ClassLoader classLoader) throws ClassNotFoundException {
    String className = this.getBeanClassName();
    if (className == null) {
        return null;
    } else {
        // 该方法就是在加载类
        Class<?> resolvedClass = ClassUtils.forName(className, classLoader);
        this.beanClass = resolvedClass;
        return resolvedClass;
    }
}

实例化 + 初始化

实例化过程分为实例化前->实例化->实例化后

实例化前和实例化后实际上都类似于钩子函数,例如在实例化前,程序员可以自己生成一个Bean对象,而不使用Spring默认的方法来生成Bean。然后直接进入

实例化前:
如果程序员自己生成了Bean对象,就不会让Spring采用默认方法去生成Bean对象了,然后就直接进入到初始化后阶段(注意不是实例化后阶段).

@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    xxx;
    if (targetType != null) {
        // 实例化前,如果我们自己返回了一个Bean
        bean = this.applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
        if (bean != null) {
            // 直接进入到初始化后阶段
            bean = this.applyBeanPostProcessorsAfterInitialization(bean, beanName);
        }
    }
    xxx;

    return bean;
}

实例化 > 初始化:
调用Spring默认的方法进行实例化:
实例化 -> 填充属性 (先执行实例化后,再填充属性) -> 执行aware方法 -> 初始化前 -> 初始化 -> 初始化后(AOP)

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
    xxxx;
    beanInstance = this.doCreateBean(beanName, mbdToUse, args);
    if (this.logger.isTraceEnabled()) {
        this.logger.trace("Finished creating instance of bean '" + beanName + "'");
    }

    return beanInstance;
}

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
    BeanWrapper instanceWrapper = null;
    xxxx;

    if (instanceWrapper == null) {
        // 实例化
        instanceWrapper = this.createBeanInstance(beanName, mbd, args);
    }

    xxx;
    // 填充属性
    // 事实上,先执行实例化后的钩子函数,再填充属性
    this.populateBean(beanName, mbd, instanceWrapper);

    // 先调用invokeAwareMethods方法
    // 初始化前方法: applyBeanPostProcessorsBeforeInitialization
    // 初始化:invokeInitMethods
    // 初始化后:applyBeanPostProcessorsAfterInitialization
    exposedObject = this.initializeBean(beanName, exposedObject, mbd);

}

十四、Bean的生命周期 - 图1