内容简介:在分析spring容器的创建过程中分析了bean的创建过程。由于创建过程步骤还是比较多的于是就新开一篇博客来详细分析下beanFactory的getBean方法做了哪些操作。分析的是通过beanType获取bean,因为根据type获取其实最终调用的也是根据beanName获取bean。这个方法的目的是根据类型获取beanNames:resolveNamedBean的操作源码:
前言
在分析spring容器的创建过程中分析了bean的创建过程。由于创建过程步骤还是比较多的于是就新开一篇博客来详细分析下beanFactory的getBean方法做了哪些操作。分析的是通过beanType获取bean,因为根据type获取其实最终调用的也是根据beanName获取bean。
resolveNamedBean:
这个方法的目的是根据类型获取beanNames:
- getBeanNamesForType:
-
先从缓存中获取该类型的所有beanName。
-
如果1没有获取到执行doGetBeanNamesForType:
- 遍历所有的bean查找符合该类型的的单例bean和单例bean工厂对象。
- 从
manualSingletonNames
(容器创建时无参构造函数初始化的bean)中获取符合的单例bean和单例bean工厂对象。(这边要注意在返回工厂bean名称时需要加上&
) - 返回所有该对象或对象工厂的集合。
-
将获取的beanNames放入缓存中。
-
- 筛选出这些beanName中不在beanDefinitionMap集合中或者允许自动注入的bean。
- 如果1中获取的beanNames大于一个,获取需要的beanName:(在这一步的时候已经调用getBean(beanName获取了对象))
- determinePrimaryCandidate来解析
@Primary
信息。如果只有一个beanName的定义信息被注册到该beanFactory或者该beanFactory的parentBeanFactory
中 并且该beanName的定义信息为Primary。返回该beanName。 - 如果1没获取到determineHighestPriorityCandidate获取。遍历获取这些bean的
@Priority
的优先级代号(数字越小优先级越高),返回优先级最高的bean名称。
- determinePrimaryCandidate来解析
- 获取到beanName后通过beanName返回包含该对象的NamedBeanHolder。
resolveNamedBean的操作源码:
//if not allow cache all bean or allowEagerInit ? 这个条件看不懂 //isConfigurationFrozen if is true mean this context init finish //get bean name from beanDefinitionNames and manualSingletonNames if (!isConfigurationFrozen() || type == null || !allowEagerInit) { return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit); } // if allow cache all bean get bean name from cache first(isConigurationFrozen is true) Map<Class<?>, String[]> cache = // includeNonSingletons : 是否包含非单例对象 (includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType); String[] resolvedBeanNames = cache.get(type); if (resolvedBeanNames != null) { return resolvedBeanNames; } // if can not get this bean type from cache ,get bean name from beanDefinitionNames and manualSingletonNames resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true); // here is some safe check: such as whether or not this bean classLoader to the beanFatory classLoader(具体我也不太清楚) if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) { cache.put(type, resolvedBeanNames); // put this beanname to cache } return resolvedBeanNames; 复制代码
doGetBeanNamesForType
操作源码:
List<String> result = new ArrayList<>(); // Check all bean definitions. for (String beanName : this.beanDefinitionNames) { // Only consider bean as eligible if the bean name // is not defined as alias for some other bean. if (!isAlias(beanName)) { try { RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); // Only check bean definition if it is complete. if (!mbd.isAbstract() && (allowEagerInit || (mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading()) && !requiresEagerInitForType(mbd.getFactoryBeanName()))) { // In case of FactoryBean, match object created by FactoryBean. boolean isFactoryBean = isFactoryBean(beanName, mbd); BeanDefinitionHolder dbd = mbd.getDecoratedDefinition(); boolean matchFound = (allowEagerInit || !isFactoryBean || (dbd != null && !mbd.isLazyInit()) || containsSingleton(beanName)) && (includeNonSingletons || (dbd != null ? mbd.isSingleton() : isSingleton(beanName))) && isTypeMatch(beanName, type); if (!matchFound && isFactoryBean) { // In case of FactoryBean, try to match FactoryBean instance itself next. beanName = FACTORY_BEAN_PREFIX + beanName; matchFound = (includeNonSingletons || mbd.isSingleton()) && isTypeMatch(beanName, type); } if (matchFound) { result.add(beanName); } } } catch (CannotLoadBeanClassException ex) { } catch (BeanDefinitionStoreException ex) { } } } // Check manually registered singletons too. for (String beanName : this.manualSingletonNames) { try { // In case of FactoryBean, match object created by FactoryBean. if (isFactoryBean(beanName)) { if ((includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type)) { result.add(beanName); // Match found for this bean: do not match FactoryBean itself anymore. continue; } // In case of FactoryBean, try to match FactoryBean itself next. beanName = FACTORY_BEAN_PREFIX + beanName; } // Match raw bean instance (might be raw FactoryBean). if (isTypeMatch(beanName, type)) { result.add(beanName); } } catch (NoSuchBeanDefinitionException ex) { } } return StringUtils.toStringArray(result); 复制代码
getBean(beanName):
该方法通过beanName获取bean,实际操作在 doGetBean
方法中:
- 该方法先是判断该bean是否被注册(工厂bean需去除
&
),之后调用getSingleton
试图获取bean实例:- 从单例对象缓存中获取bean。
- 若1未获取到并且该对象正在创建则锁定单例缓存从早期创建的对象中获取bean(待补全详细)。
- 若2依旧未获取到并且允许提前创建早期对象则获取该bean的单例工厂,存在则创建并返回。 该方法试图获取bean对象。
- 如果
getSingleton
未获取到。将bean置为创建状态。之后创建bean,创建过程将bean分成了单例,多例和其他三种情况来创建。
createBean创建对象:
调用resolveBeforeInstantiation:
调用来获取bean对象。遍历BeanPostProcessors如果是InstantiationAwareBeanPostProcessor接口调用处理器的postProcessBeforeInstantiation来获取对象,如果获取到了则调用处理器的postProcessAfterInitialization获取对象,并返回。
doCreateBean:
如果resolveBeforeInstantiation未获取到对象使用doCreateBean创建对象:
- createBeanInstance创建未初始化对象。如果beanDefinition没有FactoryMethodName则调用instantiateBean来创建对象,如果有则调用instantiateUsingFactoryMethod来创建对象。之后封装成BeanWrapper返回。
- applyMergedBeanDefinitionPostProcessors调用。该方法找出MergedBeanDefinitionPostProcessor调用postProcessMergedBeanDefinition。(CommonAnnotationBeanPostProcessor,AutowiredAnnotationBeanPostProcessor,RequiredAnnotationBeanPostProcessor,ApplicationListenerDetector)AutowiredAnnotationBeanPostProcessor处理器为bean的beanDefinition添加了@Autowired和@Value注解属性,给该处理器的injectionMetadataCache属性添加需要注入信息对象的InjectionMetadata。 ApplicationListenerDetector往它的singletonNames属性中添加了该beanDefinition。
- 调用addSingletonFactory往工厂的singletonFactories属性中添加了该对象的早期对象来解决循环引用问题。
- 调用populateBean方法:
- 查找所有的InstantiationAwareBeanPostProcessor。 (ConfigurationClassPostProcessor),如果有处理器postProcessAfterInstantiation方法返回false则直接return
populateBean
方法。不对bean进行初始化修改。 - 调用InstantiationAwareBeanPostProcessor的postProcessPropertyValues。AutowiredAnnotationBeanPostProcessor执行doResolveDependency来给当前处理的bean注入
@Autowired
和@Value
的属性,取出之前缓存的该对象InjectionMetadata,调用inject来设置@Autowired
依赖属性(期间调用doResolveDependency来获取真正需要注入的属性)。 - doResolveDependency操作详解:
@Priority
- applyPropertyValues()
- 查找所有的InstantiationAwareBeanPostProcessor。 (ConfigurationClassPostProcessor),如果有处理器postProcessAfterInstantiation方法返回false则直接return
- 调用initializeBean:
- 如果该类实现了Aware接口(BeanNameAware,BeanClassLoaderAware,BeanFactoryAware),给该类设置名称,类加载器,工厂等属性。
- applyBeanPostProcessorsBeforeInitialization来执行所有bean后置处理器的postProcessBeforeInitialization。遍历过程中如果有一个处理器返回了null将会终止处理,返回最后处理对象。
- invokeInitMethods执行初始化方法先执行实现InitializingBean接口的afterPropertiesSet方法,之后执行init方法。
- applyBeanPostProcessorsAfterInitialization执行后置处理器postProcessAfterInitialization方法,和2逻辑相同。
总结:
整个bean的创建和初始化过程还是相当繁琐的步骤。bean的整个生命周期还是比较多样的,有很多BeanPostProcessor在bean创建前后以及初始化过程中都对bean进行了管理,包括bean全部创建后还有着回调功能,有着丰富的拓展功能。讲得可能不明了,希望对大家有所帮助。详细的demo可以去看博主的 github 。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 从几道面试题看对象的初始化
- Go 创建对象时,如何优雅的传递初始化参数
- java中具有继承关系的类及其对象初始化顺序
- scala – 如何在try catch块中初始化val对象?
- C++ 的一大误区——深入解释直接初始化与复制初始化的区别
- 初始化监听端口
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
程序员2005精华本
《程序员》杂志社 / 电子工业 / 2006-1 / 45.00元
本书为集结了《程序员》杂志与《msdn开发精选》杂志精华。分上、下两册,内容包括人物&报道、管理与实践、程序员手册、年鉴、《程序员》技术专题、《msdn开发精选》文章精选等。一起来看看 《程序员2005精华本》 这本书的介绍吧!