SpringloC容器的依赖注入源码解析(4)—— Bean的创建(createBean)

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: createBean方法的执行流程如下:

文章目录

createBean方法的执行流程如下:


92.png


在AbstractBeanFactory的doGetBean的创建bean的方法里打上断点:


93.png


多放行几次看到了自定义的bean:


94.png


step into之后来到AbstractAutowireCapableBeanFactor的createBean中:


protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {
   if (logger.isTraceEnabled()) {
      logger.trace("Creating instance of bean '" + beanName + "'");
   }
   RootBeanDefinition mbdToUse = mbd;
   // Make sure bean class is actually resolved at this point, and
   // clone the bean definition in case of a dynamically resolved Class
   // which cannot be stored in the shared merged bean definition.
   Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
   if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
      mbdToUse = new RootBeanDefinition(mbd);
      mbdToUse.setBeanClass(resolvedClass);
   }
   // Prepare method overrides.
   try {
      mbdToUse.prepareMethodOverrides();
   }
   catch (BeanDefinitionValidationException ex) {
      throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
            beanName, "Validation of method overrides failed", ex);
   }
   try {
      // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
      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);
   }
   try {
      Object beanInstance = doCreateBean(beanName, mbdToUse, args);
      if (logger.isTraceEnabled()) {
         logger.trace("Finished creating instance of bean '" + beanName + "'");
      }
      return beanInstance;
   }
   catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
      // A previously detected exception with proper bean creation context already,
      // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
      throw ex;
   }
   catch (Throwable ex) {
      throw new BeanCreationException(
            mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
   }
}


最开始是BeanDefinition的定义,由于之前以及定义了BeanDefinition,所以要根据Definition的属性创建出来bean实例,这里用RootBeanDefinition接收容器中获取到的BeanDefinition实例。


RootBeanDefinition mbdToUse = mbd;

接下来尝试会用类加载器加载出class对象


Class<?> resolvedClass = resolveBeanClass(mbd, beanName);


进入到resolveBeanClass

protected Class<?> resolveBeanClass(final RootBeanDefinition mbd, String beanName, final Class<?>... typesToMatch)
      throws CannotLoadBeanClassException {
   try {
      if (mbd.hasBeanClass()) {
         return mbd.getBeanClass();
      }
      if (System.getSecurityManager() != null) {
         return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>) () ->
            doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
      }
      else {
         return doResolveBeanClass(mbd, typesToMatch);
      }
   }
   catch (PrivilegedActionException pae) {
      ClassNotFoundException ex = (ClassNotFoundException) pae.getException();
      throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
   }
   catch (ClassNotFoundException ex) {
      throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
   }
   catch (LinkageError err) {
      throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err);
   }
}
if (mbd.hasBeanClass()) {
   return mbd.getBeanClass();
}

如果是xml方式定义的话,会执行来做解析的工作

doResolveBeanClass(mbd, typesToMatch);


doResolveBeanClass方法里有很多classLoader,即调用事先保存的各种各样的类加载器去尝试加载class对象,由于class对象和类加载器一一对应,所以class对象会存在于其中的一个类加载器中,通过该加载器找到了对应的class对象之后,就会用对应的classLoader加载出对象来


回到createBean,下面如果获取到的class对象不为空,并且当前的BeanDefinition在解析之前没有class对象,但是却有className时(对应xml方式),此时就会拷贝一个RootBeanDefinition的副本,然后给这个副本设置上先前解析出来的class对象实例。


这样做的目的是不希望将解析的class绑定到缓存里的BeanDefinition,因为class有可能是每次都需要动态解析出来的。


if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
   mbdToUse = new RootBeanDefinition(mbd);
   mbdToUse.setBeanClass(resolvedClass);
}


注解方式不会执行上面那个if,所以会来到下面这个逻辑

mbdToUse.prepareMethodOverrides();

该方法判断BeanDefinition是否有定义方法的覆盖

public void prepareMethodOverrides() throws BeanDefinitionValidationException {
   // Check that lookup methods exist and determine their overloaded status.
   if (hasMethodOverrides()) {
      getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
   }
}

prepareMethodOverride先获取需要覆盖的方法数量,如果count==1则不存在重载,在使用CGLIB增强阶段就不需要进行校验了,直接找到某个方法进行增强即可,否则在增强阶段还需要做特殊的处理

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) {
      // Mark override as not overloaded, to avoid the overhead of arg type checking.
      mo.setOverloaded(false);
   }
}

样例:

<bean id="my TestBean" class="io.spring.test.MyTestBean">
    <lookup-method name="getUserBean" bean="teacher"/> 
    <reblaced-method name="changedMethod" replacer="replacer"/> 
</bean> 
<bean id="teacher" class="io.spring.test.Teacher"/> 
<bean id="student" class="io.spring.test.Student"/> 
<bean id="replacer" class="io.spring.test.Replacer"/>


对于replaced-method,会去验证一下MyTestBean里是否有changedMethod这个即将被替换的方法,对于lookup-method,如果该属性存在,则会去判断一下Teacher这个bean里是否有getUserBean这个方法,没有则报错。


回到createBean,通过方法覆盖验证之后来到


Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

1

主要是执行某些类型的后置处理器的操作。


@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
   Object bean = null;
   // 如果beforeInstantiationResolved还没有设置或者是false(说明还没有进行需要在实例化前执行的操作)
   if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
      // Make sure bean class is actually resolved at this point.
      // mbd.isSyntheticO默认是false
      // 如果注册了InstantiationAwareBeanPostProcessors类型的BeanPostProcessor
      if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
         Class<?> targetType = determineTargetType(beanName, mbd);
         if (targetType != null) {
            bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
            if (bean != null) {
               bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
            }
         }
      }
      mbd.beforeInstantiationResolved = (bean != null);
   }
   return bean;
}


Spring在AOP过程中产生的中间代理类就是isSynthetic的,此时的targetType是自己定义的WelcomeController,进入到applyBeanPostProcessorsBeforeInstantiation方法里:


protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
   for (BeanPostProcessor bp : getBeanPostProcessors()) {
      if (bp instanceof InstantiationAwareBeanPostProcessor) {
         InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
         Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
         if (result != null) {
            return result;
         }
      }
   }
   return null;
}

这里使用了责任链模式(Spring中的后置器基本都会使用责任链模式来处理),依次遍历实现了InstantiationAwareBeanPostProcessor接口的BeanPostProcessor实现类,并调用类里面的postProcessBeforeInstantiation看看谁来负责对bean实例的创建,如果去处理了并有了结果,就会立即返回,只要某一个后置处理器返回了结果,就会阻止后面后置处理器的执行。



只要


Object bean = resolveBeforeInstantiation(beanName, mbdToUse);


可以获取到bean实例,则会终止后续创建bean的流程,此时就表明bean实例的创建被用户接管了,Spring容器可以不用去创建了。


继续resolveBeforeInstantiation,如果bean实例已经被创建出来的话,就会执行


bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);


前面按理说已经执行了初始化,所以这里就应该执行初始化之后的操作,进入到applyBeanPostProcessorsAfterInitialization:

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
      throws BeansException {
   Object result = existingBean;
   for (BeanPostProcessor processor : getBeanPostProcessors()) {
      Object current = processor.postProcessAfterInitialization(result, beanName);
      if (current == null) {
         return result;
      }
      result = current;
   }
   return result;
}


同样使用了责任链模式,但相比先前这里不局限于InstantiationAwareBeanPostProcessor,而是所有的BeanPostProcessor,只要前一个执行返回结果,当前就可以拿到上一次执行后的结果,直到获取不到结果就返回。



Spring中的拦截器都是用到了后置处理器,使用责任链的模式来层层处理。



resolveBeforeInstantiation最后如果bean不会空则就打上已经处理过的标记。


回到createBean,此时会来到doCreateBean来让Spring创建Bean容器了。


95.png


相关文章
|
24天前
|
XML Java Android开发
Android实现自定义进度条(源码+解析)
Android实现自定义进度条(源码+解析)
51 1
|
1天前
|
XML 人工智能 Java
Spring Bean名称生成规则(含源码解析、自定义Spring Bean名称方式)
Spring Bean名称生成规则(含源码解析、自定义Spring Bean名称方式)
|
9天前
yolo-world 源码解析(六)(2)
yolo-world 源码解析(六)
19 0
|
9天前
yolo-world 源码解析(六)(1)
yolo-world 源码解析(六)
13 0
|
10天前
yolo-world 源码解析(五)(4)
yolo-world 源码解析(五)
22 0
|
10天前
yolo-world 源码解析(五)(1)
yolo-world 源码解析(五)
31 0
|
10天前
yolo-world 源码解析(二)(2)
yolo-world 源码解析(二)
21 0
|
10天前
Marker 源码解析(二)(3)
Marker 源码解析(二)
15 0
|
10天前
Marker 源码解析(一)(4)
Marker 源码解析(一)
14 0

推荐镜像

更多