深入理解 Spring finishBeanFactoryInitialization (一)

简介: 深入理解 Spring finishBeanFactoryInitialization (一)

源码入口#


上篇博文中我们看到了将Spring环境中的 BeanPostProcessor找出来,添加到BeanFactory中的beanPostProcessors中,统一维护,本片博文继续往下拓展,看下Spring如何实例化bean,以及如何实现在bean的实例化通过各种各样的后置处理器完成bean的增强


所以本次的程序入口是AbstractApplicationContext中的finishBeanFactoryInitialization(beanFactory);,源码如下,主要做了如下几件事


protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
  // Initialize conversion service for this context.
    // 为上下文初始化类型转换器
  if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
      beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
    beanFactory.setConversionService(
        beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
  }
    // 检查上下文中是否存在类型转换器
  if (!beanFactory.hasEmbeddedValueResolver()) {
    beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
  }
    // 尽早初始化LoadTimeWeaverAware bean,以便尽早注册它们的转换器。
  // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
  String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
  for (String weaverAwareName : weaverAwareNames) {
    getBean(weaverAwareName);
  }
  // Stop using the temporary ClassLoader for type matching.
    // 禁止使用临时类加载器进行类型匹配
  beanFactory.setTempClassLoader(null);
  // Allow for caching all bean definition metadata, not expecting further changes
    // 允许缓存所有的bean的定义数据
  beanFactory.freezeConfiguration();
  // Instantiate all remaining (non-lazy-init) singletons.
    // 准备实例化bean
  beanFactory.preInstantiateSingletons();
}


我们着重看他是如何创建实例化bean的,跟进beanFactory.preInstantiateSingletons();,调用beanFactory的方法准备实例化bean, 这个beanFactory就是Spring默认是bean工厂, DefaultListableBeanFactory, 源码如下:方法不算很长,逻辑也很清楚, 一开始Spring取出当前上下文中所有的BeanName列表,因为在执行到这里之前,已经完成包扫描了所以说这个盛放beanName的list里面存放的就是所有的需要实例化的对象的全集,包含Spring自己的,和程序员自己添加的还包含Aspectj的

所以说,当前方法的目标很明了,就是遍历这个list中的每一个beanName,然后实例化当前beanName相应的bean


当然,如果想实例化,前提是不能是抽象类,不能是接口,非懒加载, 而且针对FactoryBean还有不同的处理模式


public void preInstantiateSingletons() throws BeansException {
if (logger.isDebugEnabled()) {
  logger.debug("Pre-instantiating singletons in " + this);
}
//所有bean的名字
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
//todo 遍历一个副本以允许init方法,而init方法反过来注册新的bean定义。
// todo 盛放所有的beanName,所有的需要实例化的beanName都在这里,包括Spring断断续续添加的, Aspectj的, 程序员通过注解标识的
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
// todo 触发所有非延迟加载单例beans的初始化,主要步骤为调用getBean
for (String beanName : beanNames) {
  // todo 合并父类BeanDefinition,可以进入查看
  RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
  //todo 三个条件,抽象,单例,非懒加载
  if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
    if (isFactoryBean(beanName)) {
      Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
      // todo 如果是FactoryBean则加上&
      // todo 检验是否是 FactoryBean 类型的对象
      if (bean instanceof FactoryBean) {
        final 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);
        }
      }
    }
    else {
      // todo 因为我们没有添加FactoryBean类型的对象, 一般都会进入这个getBean
      getBean(beanName);
    }
  }
}


下面接着跟进getBean(beanName);方法,顾名思义获取Bean,再往下跟下去,就算是本文的正文开始部分了,但是我想在这里提醒自己,一个比较有分量的剧透吧,当前的getBean(beanName)它是有返回值的,一会当我们往下跟进的是时候会发现会存在递归的现象,这一点巧妙的实现了@Autowired处理setter方式实现循环引用

ok,现在继续看代码,经过了几个空方法的传递,我们来到下面的代码中,它主要做了如下几件事



首先将传递进来的name转换成了beanName


原因1: FactoryBean的实现类的存储方式和其他的类完全相同,添加上&是获取不到的, 因此我们将&去掉 原因2: 解决别名的问题



为什么在创建bean之前先调用getSingleton()?


回想一下,现在是Spring启动的过程中,是在准备实例化bean,为什么一开始就来getSingleton(),跟进源码查看这个方法,它最终实现中有一行代码是这样的Object singletonObject = this.singletonObjects.get(beanName);而这个singletonObjects就是微观层面的IOC容器,循环创建刚开始时,IOC确实是空的,但是我前面存在剧透,一开始的getBean()方法是存在递归调用现象的,直接举2个例子: 第一:假如现在在实例化A,结果有发现需要给A注入B, 那Spring是不是得获得B,怎么获得呢? 递归使用getBean(BName)完成, 第二个例子: A被添加上了@Lazy注解,是懒加载的,但是终究有一个会通过getBean(AName)获取A,这是发现A是实例化需要B,B肯定已经实例化完事了,同样是通过递归getBean(BName)实现注入, 在这两个过程中就是getSingleton()保证不会重复创建已经存在的实例

我们关注的重点其实是第二个getSingleton(beanName()->{xxx})


在第二个getSingleton()方法中才是真正的去实例化bean的方法


最后,在当前的方法最后将bean返回了


前面我就是说过了,getBean(beanName)存在递归调用的情况,为什么我会一直说这个事呢,因为如果不知道这个事的话,这些代码看起来是没有头绪的,但是明白这个事,看代码就变得很有逻辑,我在简单总结一下怎个玩这个递归呢? 假设现在通过getBean(AName)来注入A对象,但是呢发现了A依赖B对象,于是在getBean(AName)里面调用getBean(BName),通过这个方法返回出B对象完成A的注入


protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
  @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 将传递进来的name
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
// 及早的检查一下有没有已经注册了的单例对象
Object sharedInstance = getSingleton(beanName);// todo ::: name=myService时,这次来调用的就是 DefaultSingletonBeanRegistry中的 getSingleton() , 不同之处是多传递了一个true
if (sharedInstance != null && args == null) {
    // 如果存在的话,将其取出赋值给bean,后续直接返回这个bean
  bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
  // Fail if we're already creating this bean instance:
  // We're assumably within a circular reference.
    // 来到这里就说明要获取的bean还没有实例化过
    // 于是检验一下,如果是原形,直接抛异常
  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 {
      // No args -> delegate to standard getBean method.
      return parentBeanFactory.getBean(nameToLookup, requiredType);
    }
  }
  if (!typeCheckOnly) {
      // 将当前的beanName存放到AlreadeyCreated这个set集中,标识这个bean被创建了
    markBeanAsCreated(beanName);
  }
  try {
    final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
    checkMergedBeanDefinition(mbd, beanName, args);
    // Guarantee initialization of beans that the current bean depends on.
    // 确保当前bean所依赖的bean都已经初始化好了
    String[] dependsOn = mbd.getDependsOn();
    if (dependsOn != null) {
      for (String dep : dependsOn) {
        if (isDependent(beanName, dep)) {
          throw new BeanCreationException(mbd.getResourceDescription(), beanName,
              "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
        }
        registerDependentBean(dep, beanName);
        try {
          getBean(dep);
        }
        catch (NoSuchBeanDefinitionException ex) {
          throw new BeanCreationException(mbd.getResourceDescription(), beanName,
              "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
        }
      }
    }
    // Create bean instance.
    if (mbd.isSingleton()) {
      // 实例化bean
      sharedInstance = getSingleton(beanName, () -> { 
                // 真正的完成bean的创建
          return createBean(beanName, mbd, args);
      });
      bean = 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);
      }
      bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
    }
    else {
      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 {
        Object scopedInstance = scope.get(beanName, () -> {
          beforePrototypeCreation(beanName);
          try {
            return createBean(beanName, mbd, args);
          }
          finally {
            afterPrototypeCreation(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;
  }
}
// Check if required type matches the type of the actual bean instance.
if (requiredType != null && !requiredType.isInstance(bean)) {
  try {
    T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
    if (convertedBean == null) {
      throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
    }
    return convertedBean;
  }
  catch (TypeMismatchException ex) {
    if (logger.isDebugEnabled()) {
      logger.debug("Failed to convert bean '" + name + "' to required type '" +
          ClassUtils.getQualifiedName(requiredType) + "'", ex);
    }
    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
  }
}
return (T) bean;
}


经过了上面一顿扯,然后我们继续往下跟,看看createBean(beanName, mbd, args)方法中是如何实例化我们的Bean的, 上面的方法是在AbstractBeanFactory中,createBean(beanName, mbd, args)是它的抽象方法, 那实现类是哪个呢?

AbstractAutowireCapableBeanFactory,隆重的夸一下这个类,Spring都称赞这个类是有有才华的

相关文章
|
Java Spring 容器
spring之HttpInvoker
  一、HttpInvoker是常用的Java同构系统之间方法调用实现方案,是众多Spring项目中的一个子项目。顾名思义,它通过HTTP通信即可实现两个Java系统之间的远程方法调用,使得系统之间的通信如同调用本地方法一般。
2325 0
|
8月前
|
缓存 Java 数据库连接
|
5月前
|
存储 设计模式 Java
【Spring】——Spring简单 读和取(二)
【Spring】——Spring简单 读和取
36 0
【Spring】——Spring简单 读和取(二)
|
8月前
|
XML Java 程序员
|
8月前
|
XML Java 数据格式
|
10月前
|
存储 前端开发 Java
Spring 代码优化技巧(大全1)(二)
Spring 代码优化技巧(大全1)
113 0
|
10月前
|
缓存 Java 数据库连接
Spring 代码优化技巧(大全2)(二)
Spring 代码优化技巧(大全2)
71 0
|
XML 存储 Java
Spring的使用
Spring的使用
208 0
Spring的使用
|
Java Spring 容器
Spring(二)
Spring(二)
76 0
Spring(二)
|
XML 前端开发 Java
Spring(一)
Spring(一)
82 0
Spring(一)