Spring bean生命周期[2]

377 阅读3分钟

「这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战

书接上文,上文谈到了Bean生命周期的第二步的是否是工厂bean:

是factoryBean

什么是factoryBean?

  • 工厂bean。
 if (isFactoryBean(beanName)) {
    Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
    if (bean instanceof FactoryBean) {
       FactoryBean<?> factory = (FactoryBean<?>) bean;
       boolean isEagerInit;
       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) {
          getBean(beanName);
       }
    }
 }

isFactoryBean(beanName):

 public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {
    String beanName = transformedBeanName(name);
    Object beanInstance = getSingleton(beanName, false);
    if (beanInstance != null) {
       return (beanInstance instanceof FactoryBean);
    }
    // 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);
    }
    return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
 }

如何根据名字判断?

第一步:尝试从单例池取,取到了的话,判断是否是(instanceof)factoryBean。

第二步:单例池获取不到,且当前名字不在BDmap里,且父BeanFactory是ConfigurableBeanFactory:

那么就去父的BeanFactory里尝试查询。

MVC就是这么做的,其实有一点像双亲委派的感觉。

第三步:没有的话,那就只能本类中获取了。

这一步会根据BD,来查看是否是FactoryBean了。

FactoryBean.getObject是什么时候调用的?

  • 其实是在context的getBean里调用的。对应的代码:

     Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
    

isEagerInit

如果实现了SmartFactoryBean且是isEagerInit=true,这里就回去初始化了。否则就不初始化。

不是factoryBean

直接调用getBean,生成bean对象。

 else {
    getBean(beanName);
 }

getBean(name)

这个方法其实从使用场景来看,更确切的名字是:

  • getOrCreateBean

调用的方法其实是doGetBean() 方法。

根据前面解析的代码,可以知道:

  • 这里的名字可以是$.....(这个是获取factoryBean),也可以是类名,也可以是别名(aliasMap里会存)。

这个名字会在

 String beanName = transformedBeanName(name);

这里解析成符合规范的名字。

流程

首先是去单例池尝试获取:

 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 + "'");
       }
    }
    beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
 }

如果获取不到,那么就得去创建。

这里有2个case:是单例,但没创建;还有不是单例的是prototype的。

这两种都需要创建。

对应的就是下面的else部分的代码。

这里也能分作多部份。

检查是否是prototype且在创建

 if (isPrototypeCurrentlyInCreation(beanName)) {
    throw new BeanCurrentlyInCreationException(beanName);
 }

这里和循环依赖有关系。

检查父beanFactory是否有该bean

 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);
    }
 }

这里和上面的类似,如果自己的BDMap里没有该bean,且该beanFactory有父beanFactory,就委托给上面的父beanFactory来创建该bean。

那么,如果没有父BeanFactory,往下就得自己处理了。

自己创建

首先当然是获取BD了,根据之前的描述我们也知道这里需要获取一下mergedBD(也就是综合一下继承关系来生成一个包含我们需要的所有信息的BD),并检查一下。

 RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
 //这一步会检查一下是不是抽象的BD,是的话就直接报错了,因为根据之前的描述我们也知道抽象的BD是不能构造成bean的。
 checkMergedBeanDefinition(mbd, beanName, args);

获取到了BD,接下来要正式走创建bean的流程了。 这里的流程比较复杂,我们留到下一篇文章讲。