Spring IOC 容器源码分析 - getBean调用方法解析(二)
1.getObjectForBeanInstance方法
/* * 如果 sharedInstance 是普通的单例 bean,下面的方法会直接返回。但如果 * sharedInstance 是 FactoryBean 类型的,则需调用 getObject 工厂方法获取真正的 * bean 实例。如果用户想获取 FactoryBean 本身,这里也不会做特别的处理,直接返回 * 即可。毕竟 FactoryBean 的实现类本身也是一种 bean,只不过具有一点特殊的功能而已。 */ bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
getObjectForBeanInstance方法
protected Object getObjectForBeanInstance( Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) { // 如果 name 以 & 开头,但 beanInstance 却不是 FactoryBean,则认为有问题。 if (BeanFactoryUtils.isFactoryDereference(name)) { if (beanInstance instanceof NullBean) { return beanInstance; } if (!(beanInstance instanceof FactoryBean)) { throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass()); } } /* * 表明 beanInstance 是一个普通的bean,直接返回beanInstance */ if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) { return beanInstance; } Object object = null; if (mbd == null) { /* * 若 BeanDefinition 为 null,则从缓存中加载 Bean 对象 */ object = getCachedObjectForFactoryBean(beanName); } if (object == null) { // 经过前面的判断,到这里可以保证 beanInstance 是 FactoryBean 类型的,所以可以进行类型转换 FactoryBean<?> factory = (FactoryBean<?>) beanInstance; // containsBeanDefinition 检测 beanDefinitionMap 也就是在所有bean配置项已经加载的类中 // 检测是否定义 beanName if (mbd == null && containsBeanDefinition(beanName)) { // 将存储 XML 配置文件的 GenericBeanDefinition 转换为 RootBeanDefinition, // 如果指定 BeanName 是子 Bean 的话同时会合并父类的相关属性 mbd = getMergedLocalBeanDefinition(beanName); } // 是否是用户定义的,而不是应用程序本身定义的 boolean synthetic = (mbd != null && mbd.isSynthetic()); // 核心处理方法,使用 FactoryBean 获得 Bean 对象 object = getObjectFromFactoryBean(factory, beanName, !synthetic); } return object; }
getObjectFromFactoryBean方法
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) { /* * FactoryBean 也有单例和非单例之分,针对不同类型的 FactoryBean,这里有两种处理方式: * 1. 单例 FactoryBean 生成的 bean 实例也认为是单例类型。需放入缓存中,供后续重复使用 * 2. 非单例 FactoryBean 生成的 bean 实例则不会被放入缓存中,每次都会创建新的实例 */ // <1> 为单例模式且缓存中存在 if (factory.isSingleton() && containsSingleton(beanName)) { synchronized (getSingletonMutex()) { // <1.2> 从缓存中获取指定的 factoryBean Object object = this.factoryBeanObjectCache.get(beanName); if (object == null) { // 为空,则从 FactoryBean 中获取对象 去调用BeanFactory的getObject方法 object = doGetObjectFromFactoryBean(factory, beanName); // 从缓存中获取 Object alreadyThere = this.factoryBeanObjectCache.get(beanName); if (alreadyThere != null) { object = alreadyThere; } else { // <1.3> 需要后续处理 // shouldPostProcess 等价于上一个方法中的 !synthetic,用于表示是否应用后置处理 if (shouldPostProcess) { // 若该 Bean 处于创建中,则返回非处理对象,而不是存储它 if (isSingletonCurrentlyInCreation(beanName)) { // Temporarily return non-post-processed object, not storing it yet.. return object; } // 单例 Bean 的前置处理 方法,用于添加标志,当前 bean 正处于创建中,用于支持类的循环引用 beforeSingletonCreation(beanName); try { // 对从 FactoryBean 获取的对象进行后处理 // 生成的对象将暴露给 bean 引用 涉及到BeanPostProcessor,去调用了后置处理 object = postProcessObjectFromFactoryBean(object, beanName); //以上两个方法 他们记录着 Bean 的加载状态,是检测当前 Bean 是否处于创建中的关键之处,对解决 Bean 循环依赖起着关键作用。 } catch (Throwable ex) { throw new BeanCreationException(beanName, "Post-processing of FactoryBean's singleton object failed", ex); } finally { // 单例 Bean 的后置处理 afterSingletonCreation(beanName); } } // 这里的 beanName 对应于 FactoryBean 的实现类, FactoryBean 的实现类也会被实例化,并被缓存在 singletonObjects 中 if (containsSingleton(beanName)) { // FactoryBean 所创建的实例会被缓存在 factoryBeanObjectCache 中,供后续调用使用 this.factoryBeanObjectCache.put(beanName, object); } } } return object; } } // 获取非单例实例 else { // 从工厂类中获取实例 Object object = doGetObjectFromFactoryBean(factory, beanName); if (shouldPostProcess) { try { // 应用后置处理 object = postProcessObjectFromFactoryBean(object, beanName); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex); } } return object; } }
2.createBean方法
该方法是作为一个匿名内部类传入了getSingletion方法中。我们先来看看这个方法。给方法的在AbstractAutowireCapableBeanFactory中被实现。
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; // 解析 bean 的类型 Class<?> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } // Prepare method overrides. try { // 处理 lookup-method 和 replace-method 配置,Spring 将这两个配置统称为 override method mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } try { // 实例化的前置处理 // 给 BeanPostProcessors 一个机会用来返回一个代理类而不是真正的类实例 // AOP 的功能就是基于这个地方 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 { //创建 Bean 对象 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 的 class 属性。
- 处理
override属性。 - 实例化的前置处理。
- 创建 Bean 对象。
2.1.resolveBeanClass 解析指定 BeanDefinition 的 class
#resolveBeanClass(final RootBeanDefinition mbd, String beanName, final Class<?>... typesToMatch)方法,主要是解析 bean definition 的 class 类,并将已经解析的 Class 存储在 bean definition 中以供后面使用。- 如果解析的 class 不为空,则会将该 BeanDefinition 进行设置到
mbdToUse中。这样做的主要目的是,因为动态解析的 class 是无法保存到共享的 BeanDefinition 中。
2.2.prepareMethodOverrides方法
/** * * 当用户配置了 lookup-method 和 replace-method 时,Spring 需要对目标 bean 进行增强。 * 在增强之前,需要做一些准备工作,也就是 prepareMethodOverrides 中的逻辑。 * * * 在Spring容器中,单例模式的bean只会被创建一次,然后容器会缓存该单例bean的实例,等到第二次获取时,可以直接返回该bean的实例, * 而无需重新创建;原型模式的bean则是每次都会创建一个全新的bean,Spring容器并不会缓存该bean的实例以供下次使用。那么如果现在 * 有一个单例模式的bean引用了一个原型模式的bean呢?我们不希望被引用的原型模式bean被缓存,那么这个时候就需要用到lookup-method注入。 * * replaced-method * 主要作用就是替换方法体及其返回值 * <!-- ====================replace-method属性注入begin==================== --> * <bean id="replaceDog" class="com.lyc.cn.day05.replaceMethod.ReplaceDog"/> * <bean id="originalDog" class="com.lyc.cn.day05.replaceMethod.OriginalDog"> * <replaced-method name="sayHello" replacer="replaceDog"/> * </bean> * <!-- ====================replace-method属性注入end==================== --> */ public void prepareMethodOverrides() throws BeanDefinitionValidationException { // Check that lookup methods exists. if (hasMethodOverrides()) { Set<MethodOverride> overrides = getMethodOverrides().getOverrides(); synchronized (overrides) { // 循环处理每个 MethodOverride 对象 for (MethodOverride mo : overrides) { prepareMethodOverride(mo); } } } }
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException { // 获取方法名为 mo.getMethodName() 的方法数量,当方法重载时,count 的值就会大于1 int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName()); // count = 0,表明根据方法名未找到相应的方法,此时抛出异常 if (count == 0) { throw new BeanDefinitionValidationException( "Invalid method override: no method with name '" + mo.getMethodName() + "' on class [" + getBeanClassName() + "]"); } // 若 count = 1,表明仅存在已方法名为 mo.getMethodName(),这意味着方法不存在重载 else if (count == 1) { // 方法不存在重载,则将 overloaded 成员变量设为 false mo.setOverloaded(false); } }
2.3.resolveBeforeInstantiation实例化前置处理
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { Object bean = null; // 检测是否解析过,mbd.beforeInstantiationResolved 的值在下面的代码中会被设置 if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { // Make sure bean class is actually resolved at this point. 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 mbd.beforeInstantiationResolved = (bean != null); } return bean; }
- 这个方法核心就在于
applyBeanPostProcessorsBeforeInstantiation()和applyBeanPostProcessorsAfterInitialization()两个方法,before 为实例化前的后处理器应用,after 为实例化后的后处理器应用。 - 由于本文的主题是创建 bean ,关于 Bean 的增强处理后续说明。
2.4.doCreateBean 创建Bean
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // Instantiate the bean. /* * BeanWrapper 是一个基础接口,由接口名可看出这个接口的实现类用于包裹 bean 实例。 * 通过 BeanWrapper 的实现类可以方便的设置/获取 bean 实例的属性 */ BeanWrapper instanceWrapper = null; //单例模型,则从未完成的 FactoryBean 缓存中删除 if (mbd.isSingleton()) { // 从缓存中获取 BeanWrapper,并清理相关记录 instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { /* * 使用合适的实例化策略来创建新的实例:工厂方法、构造函数自动注入、简单初始化 * 创建 bean 实例,并将实例包裹在 BeanWrapper 实现类对象中返回。createBeanInstance * 中包含三种创建 bean 实例的方式: * 1. 通过工厂方法创建 bean 实例 * 2. 通过构造方法自动注入(autowire by constructor)的方式创建 bean 实例 * 3. 通过无参构造方法方法创建 bean 实例 * * 若 bean 的配置信息中配置了 lookup-method 和 replace-method,则会使用 CGLIB * 增强 bean 实例。关于这个方法 */ instanceWrapper = createBeanInstance(beanName, mbd, args); } // 此处的 bean 可以认为是一个原始的 bean 实例,暂未填充属性 final Object bean = instanceWrapper.getWrappedInstance(); // 包装的实例对象的类型 Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } // 判断是否有后置处理 // 如果有后置处理,则允许后置处理修改 BeanDefinition synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { // 后置处理修改 BeanDefinition applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex); } mbd.postProcessed = true; } } /* * 解决单例模式的循环依赖 * earlySingletonExposure 是一个重要的变量,这里要说明一下。该变量用于表示是否提前暴露 * 单例 bean,用于解决循环依赖。earlySingletonExposure 由三个条件综合而成,如下: * 条件1:mbd.isSingleton() - 表示 bean 是否是单例类型 * 条件2:allowCircularReferences - 是否允许循环依赖 * 条件3:isSingletonCurrentlyInCreation(beanName) - 当前 bean 是否处于创建的状态中 * * earlySingletonExposure = 条件1 && 条件2 && 条件3 * = 单例 && 是否允许循环依赖 && 是否存于创建状态中。 */ boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isTraceEnabled()) { logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } // 提前将创建的 bean 实例加入到 singletonFactories 中 // 这里是为了后期避免循环依赖 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // 开始初始化 bean 实例对象 Object exposedObject = bean; try { // 对 bean 进行填充,将各个属性值注入,其中,可能存在依赖于其他 bean 的属性 // 则会递归初始依赖 bean populateBean(beanName, mbd, instanceWrapper); /* * 调用初始化方法 * 进行余下的初始化工作,详细如下: * 1. 判断 bean 是否实现了 BeanNameAware、BeanFactoryAware、 * BeanClassLoaderAware 等接口,并执行接口方法 * 2. 应用 bean 初始化前置操作 * 3. 如果 bean 实现了 InitializingBean 接口,则执行 afterPropertiesSet * 方法。如果用户配置了 init-method,则调用相关方法执行自定义初始化逻辑 * 4. 应用 bean 初始化后置操作 * * 另外,AOP 相关逻辑也会在该方法中织入切面逻辑,此时的 exposedObject 就变成了 * 一个代理对象了 */ exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex; } else { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); } } //循环依赖处理 if (earlySingletonExposure) { // 获取 earlySingletonReference Object earlySingletonReference = getSingleton(beanName, false); // 只有在存在循环依赖的情况下,earlySingletonReference 才不会为空 if (earlySingletonReference != null) { // 若 initializeBean 方法未改变 exposedObject 的引用,则此处的条件为 true。 // 如果 exposedObject 没有在初始化方法中被改变,也就是没有被增强 if (exposedObject == bean) { exposedObject = earlySingletonReference; } // 处理依赖 else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length); for (String dependentBean : dependentBeans) { if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } if (!actualDependentBeans.isEmpty()) { throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been " + "wrapped. This means that said other beans do not use the final version of the " + "bean. This is often the result of over-eager type matching - consider using " + "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example."); } } } } //注册 bean try { // 注册销毁逻辑 registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); } return exposedObject; }
细节后续解析

浙公网安备 33010602011771号