spring源码分析IOC容器初始化
Posted developer_chan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring源码分析IOC容器初始化相关的知识,希望对你有一定的参考价值。
- 前言:在上文bean加载过程中还要一个非常重要的方法没有分析createBean,该方法非常重要,因此特意提出来单独分析。
createBean方法定义在AbstractBeanFactory中:
该方法根据给定的beanName、BeanDefinition和args实例化一个bean对象。所有bean实例的创建都会委托给该方法实现。
AbstractAutowireCapableBeanFactory#createBean
createBean的默认实现在AbstractAutowireCapableBeanFactory类中,代码如下:
1 protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) 2 throws BeanCreationException { 3 if (logger.isDebugEnabled()) { 4 logger.debug("Creating instance of bean ‘" + beanName + "‘"); 5 } 6 RootBeanDefinition mbdToUse = mbd; 7 8 // Make sure bean class is actually resolved at this point, and 9 // clone the bean definition in case of a dynamically resolved Class 10 // which cannot be stored in the shared merged bean definition. 11 // 确保此时的bean已经被解析了 12 // 如果获取的class属性不为null,则克隆该BeanDefinition,主要是因为动态解析的class无法保存到共享的BeanDefinition 13 Class<?> resolvedClass = resolveBeanClass(mbd, beanName); 14 if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { 15 mbdToUse = new RootBeanDefinition(mbd); 16 mbdToUse.setBeanClass(resolvedClass); 17 } 18 19 // Prepare method overrides. 20 try { 21 // 验证和准备覆盖方法 22 mbdToUse.prepareMethodOverrides(); 23 } catch (BeanDefinitionValidationException ex) { 24 throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), 25 beanName, "Validation of method overrides failed", ex); 26 } 27 28 try { 29 // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. 30 // 实例化的前置处理 31 // 给BeanPostProcessor一个机会用来返回一个代理类而不是真正的实例类 32 // AOP的功能就是基于这个地方 33 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); 34 if (bean != null) { 35 return bean; 36 } 37 } catch (Throwable ex) { 38 throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, 39 "BeanPostProcessor before instantiation of bean failed", ex); 40 } 41 42 try { 43 // 创建Bean对象 44 Object beanInstance = doCreateBean(beanName, mbdToUse, args); 45 if (logger.isDebugEnabled()) { 46 logger.debug("Finished creating instance of bean ‘" + beanName + "‘"); 47 } 48 return beanInstance; 49 } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) { 50 // A previously detected exception with proper bean creation context already, 51 // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry. 52 throw ex; 53 } catch (Throwable ex) { 54 throw new BeanCreationException( 55 mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex); 56 } 57 }
分析:
- 通过resolveBeanClass解析BeanDefinition的class属性。
- 处理override属性。
- 通过resolveBeforeInstantiation进行实例化的前置处理。
- 最后通过doCreateBean创建bean对象。
AbstractBeanFactory#resolveBeanClass
1 protected Class<?> resolveBeanClass(final RootBeanDefinition mbd, String beanName, final Class<?>... typesToMatch) 2 throws CannotLoadBeanClassException { 3 4 try { 5 if (mbd.hasBeanClass()) { 6 return mbd.getBeanClass(); 7 } 8 if (System.getSecurityManager() != null) { 9 return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>) () -> 10 doResolveBeanClass(mbd, typesToMatch), getAccessControlContext()); 11 } else { 12 return doResolveBeanClass(mbd, typesToMatch); 13 } 14 // ..... 省略异常处理 15 }
分析:
该方法主要是解析BeanDefinition的class类,如果解析的class类不为空,则将其设置到mbdToUse中,因为动态解析的class无法保存到共享的BeanDefinition中。
AbstractBeanFactory#prepareMethodOverrides
1 public void prepareMethodOverrides() throws BeanDefinitionValidationException { 2 // Check that lookup methods exists. 3 // 如果方法可以覆盖 4 if (hasMethodOverrides()) { 5 // 得到覆盖方法 6 Set<MethodOverride> overrides = getMethodOverrides().getOverrides(); 7 // 同步 8 synchronized (overrides) { 9 // 循环调用 prepareMethodOverride进行覆盖准备 10 for (MethodOverride mo : overrides) { 11 prepareMethodOverride(mo); 12 } 13 } 14 } 15 }
分析:
bean标签中的lookup-method和replace-method属性就是放在BeanDefinition的methodOverrides属性中(关于这两个属性的分析后续再来分析),这里就是对methodOverrides属性进行处理,动态为当前bean生产代理并使用对应的拦截器为bean做增强处理。
上述处理逻辑就是循环获取MethodOverride属性,然后调用prepareMethodOverride进行处理。
1 // AbstractBeanDefinition 2 protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException { 3 int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName()); 4 if (count == 0) { 5 throw new BeanDefinitionValidationException( 6 "Invalid method override: no method with name ‘" + mo.getMethodName() + 7 "‘ on class [" + getBeanClassName() + "]"); 8 } else if (count == 1) { 9 // Mark override as not overloaded, to avoid the overhead of arg type checking. 10 mo.setOverloaded(false); 11 } 12 }
分析:
根据方法名,从class中获取该方法名的个数:
- 如果方法名个数为0,则抛出BeanDefinitionValidationException异常,原因其实很简单:通过方法名去查找,而又没有找到,则说明有问题的,抛出异常。
- 如果方法名个数为1,则设置该方法未被重载(overloaded属性模式为true)。如果一个类存在多个重载方法,在方法调用的时候还需根据参数类型来判断到底重载的是哪个方法,这里通过count=1,来表示该方法未被重载,在调用的时候可以直接找方法而不需要进行方法参数的校验,相当于一个小小的优化,提升后面调用函数的速度。
AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation
1 protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { 2 Object bean = null; 3 // 如果bean不是应用系统的,有BeanPostProcessor 4 if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { 5 // Make sure bean class is actually resolved at this point. 6 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { 7 Class<?> targetType = determineTargetType(beanName, mbd); 8 if (targetType != null) { 9 // 前置处理 10 bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); 11 if (bean != null) { 12 // 后置处理 13 bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); 14 } 15 } 16 } 17 mbd.beforeInstantiationResolved = (bean != null); 18 } 19 return bean; 20 }
分析:
通过applyBeanPostProcessorsBeforeInstantiation和applyBeanPostProcessorsAfterInitialization对bean实例化前进行前置与后置处理。如果返回了代理对象,则直接返回结果,Spring后续实现AOP就是基于这个地方进行的判断。
前置处理与后置处理后续再具体进行分析。
AbstractAutowireCapableBeanFactory#doCreateBean
1 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) 2 throws BeanCreationException { 3 4 // Instantiate the bean. 5 // BeanWrapper是对Bean的包装,其接口中所定义的功能很简单包括设置获取被包装的对象、获取被包装bean的属性描述器 6 BeanWrapper instanceWrapper = null; 7 // 如果是单例模型,则从未完成的FactoryBean缓存中删除 8 if (mbd.isSingleton()) { 9 instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); 10 } 11 // 使用合适的实例化策略来创建新的实例:工厂方法、构造函数自动注入、简单初始化 12 if (instanceWrapper == null) { 13 instanceWrapper = createBeanInstance(beanName, mbd, args); 14 } 15 // 包装的对象实例 16 final Object bean = instanceWrapper.getWrappedInstance(); 17 // 包装的实例对象的类型 18 Class<?> beanType = instanceWrapper.getWrappedClass(); 19 if (beanType != NullBean.class) { 20 mbd.resolvedTargetType = beanType; 21 } 22 23 // Allow post-processors to modify the merged bean definition. 24 // 先做同步,然后判断是否有后置处理 25 synchronized (mbd.postProcessingLock) { 26 if (!mbd.postProcessed) { 27 try { 28 // 后置处理修改BeanDefinition 29 applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); 30 } catch (Throwable ex) { 31 throw new BeanCreationException(mbd.getResourceDescription(), beanName, 32 "Post-processing of merged bean definition failed", ex); 33 } 34 mbd.postProcessed = true; 35 } 36 } 37 38 // Eagerly cache singletons to be able to resolve circular references 39 // even when triggered by lifecycle interfaces like BeanFactoryAware. 40 // 解决单例模式的循环依赖 // 单例模式 运行循环依赖 41 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && 42 isSingletonCurrentlyInCreation(beanName));// 当前单例bean是否正在被创建 43 if (earlySingletonExposure) { 44 if (logger.isDebugEnabled()) { 45 logger.debug("Eagerly caching bean ‘" + beanName + 46 "‘ to allow for resolving potential circular references"); 47 } 48 // 提前将创建的bean实例加入到singletonFactories中 49 // 为了后期避免循环依赖 50 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); 51 } 52 53 // Initialize the bean instance. 54 // 开始初始化bean实例对象 55 Object exposedObject = bean; 56 try { 57 // 对bean进行填充,主要是进行属性注入,其中,可能存在依赖于其他bean的属性,则会递归初始化依赖bean 58 populateBean(beanName, mbd, instanceWrapper); 59 // 进行bean初始化 60 exposedObject = initializeBean(beanName, exposedObject, mbd); 61 } catch (Throwable ex) { 62 if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { 63 throw (BeanCreationException) ex; 64 } else { 65 throw new BeanCreationException( 66 mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); 67 } 68 } 69 70 // 循环依赖处理 71 if (earlySingletonExposure) { 72 // 获取earlySingletonReference 73 Object earlySingletonReference = getSingleton(beanName, false); 74 // 只有在循环依赖的情况下,earlySingletonReference才不会为null 75 if (earlySingletonReference != null) { 76 // 如果exposedObject没有在初始化方法中改变,也就是没有被增强 77 if (exposedObject == bean) { 78 exposedObject = earlySingletonReference; 79 } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { // 处理依赖 80 String[] dependentBeans = getDependentBeans(beanName); 81 Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length); 82 for (String dependentBean : dependentBeans) { 83 if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { 84 actualDependentBeans.add(dependentBean); 85 } 86 } 87 if (!actualDependentBeans.isEmpty()) { 88 throw new BeanCurrentlyInCreationException(beanName, 89 "Bean with name ‘" + beanName + "‘ has been injected into other beans [" + 90 StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + 91 "] in its raw version as part of a circular reference, but has eventually been " + 92 "wrapped. This means that said other beans do not use the final version of the " + 93 "bean. This is often the result of over-eager type matching - consider using " + 94 "‘getBeanNamesOfType‘ with the ‘allowEagerInit‘ flag turned off, for example."); 95 } 96 } 97 } 98 } 99 100 // Register bean as disposable. 101 try { 102 // 注册bean 103 registerDisposableBeanIfNecessary(beanName, bean, mbd); 104 } catch (BeanDefinitionValidationException ex) { 105 throw new BeanCreationException( 106 mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); 107 } 108 109 return exposedObject; 110 }
分析:
如果没有代理对象,则会进行bean对象的创建。
- 如果BeanDefinition为单例模式,首先从FactoryBean缓存中删除该beanName的缓存。
- 调用createBeanInstance方法创建一个BeanWrapper对象。
- 调用applyMergedBeanDefinitionPostProcessors对BeanDefinition进行后置处理
- 进行单例模式的循环依赖处理。
- 调用populateBean进行bean属性填充。
- 调用initializeBean进行bean初始化。
- 进行依赖检查。
- 最后注册bean。
上述列出了创建bean对象的主要步骤,过程还是比较复杂的,下面一一进行分析。主要关注点createBeanInstance、populateBean、initializeBean三个函数。
AbstractAutowireCapableBeanFactory#createBeanInstance
1 protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { 2 // Make sure bean class is actually resolved at this point. 3 // 解析bean,将bean类名解析为class引用 4 Class<?> beanClass = resolveBeanClass(mbd, beanName); 5 6 if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) { 7 throw new BeanCreationException(mbd.getResourceDescription(), beanName, 8 "Bean class isn‘t public, and non-public access not allowed: " + beanClass.getName()); 9 } 10 11 // 如果存在supplier回调,则使用给定的回调方法初始化策略 12 Supplier<?> instanceSupplier = mbd.getInstanceSupplier(); 13 if (instanceSupplier != null) { 14 return obtainFromSupplier(instanceSupplier, beanName); 15 } 16 17 // 使用FactoryBean的factor-method来创建bean,支持静态工厂和实例工厂 18 if (mbd.getFactoryMethodName() != null) { 19 return instantiateUsingFactoryMethod(beanName, mbd, args); 20 } 21 22 // Shortcut when re-creating the same bean... 23 boolean resolved = false; 24 boolean autowireNecessary = false; 25 if (args == null) { 26 // 做同步 27 synchronized (mbd.constructorArgumentLock) { 28 // 如果已缓存的解析构造函数或者工厂方法不为null,则可以利用构造函数解析 29 // 因为需要根据参数确认到底使用哪个构造函数,该过程比较消耗性能,所以采用缓存机制 30 if (mbd.resolvedConstructorOrFactoryMethod != null) { 31 resolved = true; 32 autowireNecessary = mbd.constructorArgumentsResolved; 33 } 34 } 35 } 36 // 已经解析好了,直接注入即可 37 if (resolved) { 38 // autowire自动注入,调用构造函数自动注入 39 if (autowireNecessary) { 40 return autowireConstructor(beanName, mbd, null, null); 41 } else { 42 // 使用默认构造函数构造 43 return instantiateBean(beanName, mbd); 44 } 45 } 46 47 // Need to determine the constructor... 48 // 确定解析的构造函数 49 // 主要是检查已经注册的SmartInstantiationAwareBeanPostProcessor 50 Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); 51 // 确定构造方法进行bean创建 52 if (ctors != null || 53 mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR || 54 mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { 55 return autowireConstructor(beanName, mbd, ctors, args); 56 } 57 58 // 有参数,又没有获取到构造方法,则只能调用无参构造方法来创建实例 59 // 这是一个兜底的方法 60 // No special handling: simply use no-arg constructor. 61 return instantiateBean(beanName, mbd); 62 }
分析:
bean的实例化一个比较复杂的过程。
- 如果设置Supplier回调,则调用obtainFromSupplier方法进行初始化。
- 如果存在工厂方法,则使用工厂方法进行初始化。
- 先判断缓存中是否存在构造函数,如果存在,则根据是否使用自动注入,还是默认的构造函数进行bean对象的初始化。
- 如果缓存中不存在,则需先判断到底使用哪个构造函数来完成解析工作。
- 如果上述条件还是不满足,则使用无参构造方法来创建实例。
#1.如果设置Supplier回调,则使用obtainFromSupplier方法进行初始化。
首先了解下Supplier接口(java.util.function):
- Supplier接口仅有一个功能性的get()方法,该方法会返回一个<T>类型的对象,有点类似工厂方法。
- 如果我们在创建BeanDefinition的时候设置了Supplier参数,那么其他的构造器或者工厂方法就没有作用了。
- AbstractBeanDefinition中提供了设置Supplier的入口:
AbstractAutowireCapableBeanFactory#obtainFromSupplier
1 protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) { 2 // 获得原创建的Bean的对象名 3 String outerBean = this.currentlyCreatedBean.get(); 4 // 设置新的Bean对象名到currentlyCreatedBean中 5 this.currentlyCreatedBean.set(beanName); 6 Object instance; 7 try { 8 // 调用Supplier的get(),返回一个Bean对象 9 instance = instanceSupplier.get(); 10 } finally { 11 // 设置原创建的Bean对象名到currentlyCreatedBean中 12 if (outerBean != null) { 13 this.currentlyCreatedBean.set(outerBean); 14 } else { 15 this.currentlyCreatedBean.remove(); 16 } 17 } 18 // 创建BeanWrapper对象 19 BeanWrapper bw = new BeanWrapperImpl(instance); 20 // 初始化BeanWrapper 21 initBeanWrapper(bw); 22 return bw; 23 }
分析:
- 调用Supplier#get方法,获取一个Bean实例对象。
- 根据该实例对象构建BeanWrapper对象。
- 最后初始化该对象。
如果存在工厂方法,则会调用工厂方法来完成bean的初始化工作,该方法实现比较长,并且细节复杂,由于篇幅原因放在下篇文章中解析。
总结
这里仅仅分析了doCreateBean方法中的一点点内容,如果存在Supplier回调,则会直接通过Supplier来创建Bean对象,构造函数和工厂方法则失效,下面将对分析使用工厂方法实例化Bean对象的过程。
by Shawn Chen,2019.04.23,下午。
以上是关于spring源码分析IOC容器初始化的主要内容,如果未能解决你的问题,请参考以下文章