Spring总结一:Bean的初始化过程

前言:

这篇文章并不是真正的关于Spring中Bean的初始化过程的详细介绍,只是简单介绍,在介绍Spring设计模式的文章中因为需要,链接到这篇文章,对bean的初始化过程简单说明。


bean容器的启动:

  • 读取bean的xml配置文件或者解析特定注解的类,将bean元素转换成BeanDefinition对象(BeanDefinition对象存储了bean对象的所有特征,是否单例,是否懒加载,factoryBeanName等)
  • 通过DeanDefinitionRegistry将这些bean注册到beanFactory中,保存在它的一个concurrentHashMap中
  • 将BeanDefinition注册到beanFactory之后,在这里提供了一个扩展接口,允许我们通过实现接口BeanFactoryPostProcessor在此处插入我们定义的代码。典型的例子就是PropertyPlaceholderConfigurer,我们一般在配置数据库dataSource时使用的占位符的值,就是它注入进去的。

容器中bean的实例化阶段:

  • 实例化阶段主要是通过反射或者CGLIB对bean进行实例化,在spring中给我们暴露了很多接口,我们只用实现接口就可以对bean实例化功能进行扩展。

Spring总结一:Bean的初始化过程_第1张图片

创建bean的核心方法:

protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
    //记录日志
   if (logger.isDebugEnabled()) {
      logger.debug("Creating instance of bean '" + beanName + "'");
   }
    //初始化在这个方法中真正会使用的mbd,默认情况下它就是调用时传来的参数
   RootBeanDefinition mbdToUse = mbd;
    //resolveBeanClass方法解析加载了mbd但是并没有生产Bean,它会生产一个特定的classLoad来加载mbd生成class
   Class resolvedClass = resolveBeanClass(mbd, beanName);
       //判断了是否是动态解析的bean和是否是共享合并的bean,在这种情况下mbd是无法储存的解析出来class的,所以这里克隆一下mbd对象。
   if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
      mbdToUse = new RootBeanDefinition(mbd);
      mbdToUse.setBeanClass(resolvedClass);
   }
 
    //准备覆盖的方法
   try {
      mbdToUse.prepareMethodOverrides();
   }
   catch (BeanDefinitionValidationException ex) {
      throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
            beanName, "Validation of method overrides failed", ex);
   }
 
   try {
      // 允许后处理器(BeanPostProcessors)来用代理对象替换掉真正的bean
      Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
      if (bean != null) {
         return bean;
      }
   }
   catch (Throwable ex) {
      throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
            "BeanPostProcessor before instantiation of bean failed", ex);
   }
    //创建bean
   Object beanInstance = doCreateBean(beanName, mbdToUse, args);
   if (logger.isDebugEnabled()) {
      logger.debug("Finished creating instance of bean '" + beanName + "'");
   }
   return beanInstance;
}

 

绝大多数的bean初始化都在finishiBeanFacotyInitiallization方法中。简单介绍下bean的实例化过程:

  1. 获取该beanDefinition对应的字节码;
  2. prepareMethodOverrides。对override属性进行标记和验证。prepareMethodOverrides方法的方法校验和预处理。查看AbstractBeanDefinition中的prepareMethodOverrides方法:
public void prepareMethodOverrides() throws BeanDefinitionValidationException {
   //获取方法的重写对象
   MethodOverrides methodOverrides = getMethodOverrides();
   if (!methodOverrides.isEmpty()) {
      for (MethodOverride mo : methodOverrides.getOverrides()) {
        //标记未重载的方法
         prepareMethodOverride(mo);
      }
   }
}
 
 
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
    //查看对应类中叫这个名字的方法的个数
   int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
   if (count == 0) {
        //没有就抛出异常
      throw new BeanDefinitionValidationException(
            "Invalid method override: no method with name '" + mo.getMethodName() +
            "' on class [" + getBeanClassName() + "]");
   }
   else if (count == 1) {
      //将其标记为没有重载,用来减少开系统开销
      mo.setOverloaded(false);
   }
}

   这两个方法的实现原理其实是在bean实例化的时候如果检测到存在methodOverrides属性(lookup-method和replace-method两个配置会被存放到其中),动态的为当前bean生成代理并使用对应的拦截器为bean做增强处理,具体的实现逻辑在bean的实例化部分。如果一个类中存在若干个重载方法(就是count大于1的情况下),会在方法调用及增强的时候还需要根据参数类型进行批评,最终确认当前调用的到底是哪个方法。

        但spring将其中一种特别情况在这里做了优化处理,没有重载方法的时候(count等于1的情况),并标记为没有重载,这样在后续的使用中直接就可以无需在根据参数进行判断是哪个具体方法,还提前做了方法存在性的校验。

   3.  调用doCreateBean方法,进行具体的实例化过程

       3.1 如果是单例,则从bean工厂实例的缓存中获取bean对象

if (mbd.isSingleton()) {
   instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}

      创建bean实例包括很多详细的步骤,后面会专门写一篇跟着Spring源码进行详细讲解,主要步骤包括:

  1.  从beanFactory中读取bean的定义,beanDefinition,然后实例化Bean对象;
  2.  设置Bean的属性;
  3.  如果我们通过各种Aware接口声明了依赖关系,则会注入Bean对容器基础设施层的依赖。具体包括BeanNameAware、BeanFactoryAware和ApplicationContextAware,分别会注入Bean ID、BeanFactory或者ApplicationContext
  4. 调用BeanPostProcessor的前置初始化方法,postProcessBeforeInitialization。
  5. 如果实现了InitializingBean接口,则会调用afterPropertiesSet方法;
  6. 调用Bean资深的init方法;
  7. 调用BeanPostProcessor的后置初始化方法postProcessAfterInitialization;
  8. 创建完毕;
  9. 执行DisposableBean.destory() 方法;
  10. 执行自定义的destory方法或者@PreDestory标注的方法;
  11. 销毁对象完毕

你可能感兴趣的:(Spring,源码,spring,java)