本文共 17943 字,大约阅读时间需要 59 分钟。
一般来说,Spring框架启动流程大体上分成两个大的步骤:IoC容器初始化和Bean的依赖注入。
Bean的依赖注入大致可分为如下过程:
转换对应beanName;
尝试从缓存中加载单例;
获取单例
创建Bean
考虑到传入的beanName可能是别名,也有可能是FactoryBean,因此需要进行必要的转换。简单来说,如果是FactoryBean的话,去除前面的修饰符“&”;如果是alias,取指定alias所表示的最终beanName。
Spring框架中尝试加载单例的代码如下:
public Object getSingleton(String beanName) { return this.getSingleton(beanName, true); }protected Object getSingleton(String beanName, boolean allowEarlyReference) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) { Map var4 = this.singletonObjects; synchronized(this.singletonObjects) { singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { ObjectFactory singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } }
在得到bean的实例后需要调用getObjectForBeanInstance方法来检测一下正确性,其实就是检测当前bean是否为FactoryBean类型的bean,如果是,需要调用对应的getObject方法作为返回值。
protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd) { if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) { throw new BeanIsNotAFactoryException(this.transformedBeanName(name), beanInstance.getClass()); } else if (beanInstance instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) { Object object = null; if (mbd == null) { object = this.getCachedObjectForFactoryBean(beanName); } if (object == null) { FactoryBean factory = (FactoryBean)beanInstance; if (mbd == null && this.containsBeanDefinition(beanName)) { mbd = this.getMergedLocalBeanDefinition(beanName); } boolean synthetic = mbd != null && mbd.isSynthetic(); object = this.getObjectFromFactoryBean(factory, beanName, !synthetic); } return object; } else { return beanInstance; } }
上述代码中对于非FactoryBean不做任何处理,而将从Factory中解析bean的工作委托给了getObjectFromFactoryBean方法。
protected Object getObjectFromFactoryBean(FactoryBean factory, String beanName, boolean shouldPostProcess) { if (factory.isSingleton() && this.containsSingleton(beanName)) { synchronized(this.getSingletonMutex()) { Object object = this.factoryBeanObjectCache.get(beanName); if (object == null) { object = this.doGetObjectFromFactoryBean(factory, beanName); Object alreadyThere = this.factoryBeanObjectCache.get(beanName); if (alreadyThere != null) { object = alreadyThere; } else { if (object != null && shouldPostProcess) { try { object = this.postProcessObjectFromFactoryBean(object, beanName); } catch (Throwable var9) { throw new BeanCreationException(beanName, "Post-processing of FactoryBean's singleton object failed", var9); } } this.factoryBeanObjectCache.put(beanName, object != null ? object : NULL_OBJECT); } } return object != NULL_OBJECT ? object : null; } } else { Object object = this.doGetObjectFromFactoryBean(factory, beanName); if (object != null && shouldPostProcess) { try { object = this.postProcessObjectFromFactoryBean(object, beanName); } catch (Throwable var11) { throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", var11); } } return object; } }
代码中只有一处需要注意的,那就是如果bean是单例的,那就要保证全局唯一,也因为是单例,可以不必重复创建,使用缓存来提高性能。最后去调用doGetObjectFromFactoryBean方法。
private Object doGetObjectFromFactoryBean(final FactoryBean factory, String beanName) throws BeanCreationException { Object object; try { if (System.getSecurityManager() != null) { AccessControlContext acc = this.getAccessControlContext(); try { object = AccessController.doPrivileged(new PrivilegedExceptionAction
可以看到,通过直接调用getObject方法获取bean,并通过postProcessObjectFromFactoryBean方法完成相应的后处理。Spring获取bean的规则中有一条:尽可能保证所有bean初始化后都会调用注册的BeanPostProcessor的postProcessAfterInitialization方法进行处理。
如果当前缓存中不存在对应的单例Bean,那就必须从头开始加载Bean,ObjectFactory的核心部分就是调用createBean方法。
sharedInstance = this.getSingleton(beanName, new ObjectFactory() { public Object getObject() throws BeansException { try { return AbstractBeanFactory.this.createBean(beanName, mbd, args); } catch (BeansException var2) { AbstractBeanFactory.this.destroySingleton(beanName); throw var2; } } });
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException { if (this.logger.isDebugEnabled()) { this.logger.debug("Creating instance of bean '" + beanName + "'"); } this.resolveBeanClass(mbd, beanName, new Class[0]); try { mbd.prepareMethodOverrides(); } catch (BeanDefinitionValidationException var5) { throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName, "Validation of method overrides failed", var5); } Object beanInstance; try { beanInstance = this.resolveBeforeInstantiation(beanName, mbd); if (beanInstance != null) { return beanInstance; } } catch (Throwable var6) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var6); } beanInstance = this.doCreateBean(beanName, mbd, args); if (this.logger.isDebugEnabled()) { this.logger.debug("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; }
在调用doCreateBean方法之前,先调用了prepareMethodOverrides和resolveBeforeInstantiation两个方法,前者完成override属性处理,后者完成bean实例化的前置处理,此处暂不叙述,读者可关注后续文章。
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, Object[] args) { BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { //如果是单例则需要首先清除缓存 instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { //根据指定bean使用对应的策略创建新的实例 instanceWrapper = this.createBeanInstance(beanName, mbd, args); } final Object bean = instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null; Class beanType = instanceWrapper != null ? instanceWrapper.getWrappedClass() : null; Object var7 = mbd.postProcessingLock; synchronized(mbd.postProcessingLock) { if (!mbd.postProcessed) { this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); mbd.postProcessed = true; } } //如果是单例并且允许循环依赖并且当前bean正在创建中检测到循环依赖,则需要提早曝光 boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName); if (earlySingletonExposure) { if (this.logger.isDebugEnabled()) { this.logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } this.addSingletonFactory(beanName, new ObjectFactory
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) { Class beanClass = this.resolveBeanClass(mbd, beanName, new Class[0]); if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn't public, and non-public access not allowed: " + beanClass.getName()); } else if (mbd.getFactoryMethodName() != null) { //如果工厂方法不为空则使用工厂方法初始化策略 return this.instantiateUsingFactoryMethod(beanName, mbd, args); } else { boolean resolved = false; boolean autowireNecessary = false; if (args == null) { Object var7 = mbd.constructorArgumentLock; synchronized(mbd.constructorArgumentLock) { //根据参数确定调用的构造方法或者工厂方法 if (mbd.resolvedConstructorOrFactoryMethod != null) { resolved = true; autowireNecessary = mbd.constructorArgumentsResolved; } } } if (resolved) { //确定使用构造方法自动注入还是使用默认构造方法构造 return autowireNecessary ? this.autowireConstructor(beanName, mbd, (Constructor[])null, (Object[])null) : this.instantiateBean(beanName, mbd); } else { Constructor [] ctors = this.determineConstructorsFromBeanPostProcessors(beanClass, beanName); //确定使用构造方法自动注入还是使用默认构造方法构造 return ctors == null && mbd.getResolvedAutowireMode() != 3 && !mbd.hasConstructorArgumentValues() && ObjectUtils.isEmpty(args) ? this.instantiateBean(beanName, mbd) : this.autowireConstructor(beanName, mbd, ctors, args); } } }
从代码中可以看出,Spring通过autowireConstructor和instantiateBean两个方法创建Bean实例。前者逻辑复杂,代码量巨大,但从其功能实现的角度考虑了如下几个方面:
构造函数参数的确定(隐式参数、缓存、配置文件);
构造函数的确定;
根据确定的构造函数转换对应的参数类型;
构造函数不确定性的验证;
根据实例化策略以及得到的构造函数寄构造函数参数实例化Bean。
后者逻辑简单,由于不需要考虑参数,因此直接调用实例化策略进行实例化就可以了。实例化操作结束后,需要注入属性。重点是
autowireByName和autowireByType两个方法。protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) { PropertyValues pvs = mbd.getPropertyValues(); if (bw == null) { if (!((PropertyValues)pvs).isEmpty()) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); } } else { boolean continueWithPropertyPopulation = true; if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) { Iterator i$ = this.getBeanPostProcessors().iterator(); while(i$.hasNext()) { BeanPostProcessor bp = (BeanPostProcessor)i$.next(); if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation = false; break; } } } } if (continueWithPropertyPopulation) { if (mbd.getResolvedAutowireMode() == 1 || mbd.getResolvedAutowireMode() == 2) { MutablePropertyValues newPvs = new MutablePropertyValues((PropertyValues)pvs); if (mbd.getResolvedAutowireMode() == 1) { this.autowireByName(beanName, mbd, bw, newPvs); } if (mbd.getResolvedAutowireMode() == 2) { this.autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = this.hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = mbd.getDependencyCheck() != 0; if (hasInstAwareBpps || needsDepCheck) { PropertyDescriptor[] filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); if (hasInstAwareBpps) { Iterator i$ = this.getBeanPostProcessors().iterator(); while(i$.hasNext()) { BeanPostProcessor bp = (BeanPostProcessor)i$.next(); if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp; pvs = ibp.postProcessPropertyValues((PropertyValues)pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvs == null) { return; } } } } if (needsDepCheck) { this.checkDependencies(beanName, mbd, filteredPds, (PropertyValues)pvs); } } this.applyPropertyValues(beanName, mbd, bw, (PropertyValues)pvs); } } }
此时Spring已经完成了bean的实例化和属性的填充,接着便会调用用户设定的初始化方法。一般而言,用户可以有三种途径自定义初始化方法,后续文章会有详细叙述,敬请关注。
笔者花了两篇博文的篇幅大致介绍了Spring容器的启动过程,还有很多细节方面并未涉及,例如循环依赖、具体属性值注入等。平时开发时对于容器启动时打印的日志信息毫无感觉,现在读者可以结合博文再去关注日志信息,相信会有更深的体会。祝好!
转载地址:http://zsgmi.baihongyu.com/