文章目录
createBean方法的执行流程如下:
在AbstractBeanFactory的doGetBean的创建bean的方法里打上断点:
多放行几次看到了自定义的bean:
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容器了。