Spring源碼解析 Bean屬性填充
前言
在上一篇文章中,我們分析了Spring中Bean的實(shí)例化過程,在結(jié)尾我們知道了雖然bean的實(shí)例化完成了,但是其中的屬性還沒有被注入,今天我們就接著來分析屬性是如何被注入的。
屬性填充
實(shí)例化完成后,回到上面第3條的doCreateBean
方法中,看一下用BeanWrapper
產(chǎn)生的原生對(duì)象,里面dao
這個(gè)屬性還是null
值。
回歸一下之前的代碼,接下來要調(diào)用populateBean
方法進(jìn)行屬性的填充:
Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); exposedObject = initializeBean(beanName, exposedObject, mbd); }
看一下populateBean
中的核心代碼:
for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvs == null) { return; } } }
這里通過getBeanPostProcessors
方法獲得當(dāng)前注冊(cè)的所有后置處理器,如果屬于InstantiationAwareBeanPostProcessor
類型,則調(diào)用它的postProcessPropertyValues
方法。通過遍歷,可以知道當(dāng)前spring中存在7個(gè)后置處理器:
我們主要來看一下AutowiredAnnotationBeanPostProcessor
,因?yàn)樗?fù)責(zé)對(duì)添加了 @Autowired
、@Value
等注解的屬性進(jìn)行依賴的填充。進(jìn)入它的postProcessPropertyValues
方法:
public PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException { InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs); try { metadata.inject(bean, beanName, pvs); } //異常處理代碼省略... return pvs; }
這里的InjectionMetadata
可以理解為要注入的屬性的元數(shù)據(jù),在它里面維護(hù)了一個(gè)Collection
,來存放所有需要注入的bean:
private final Collection<InjectedElement> injectedElements;
進(jìn)入findAutowiringMetadata
方法:
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) { String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName()); InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey); //省略非重要代碼... return metadata; }
在執(zhí)行完這一步后,就把需要填充的屬性放進(jìn)了剛才提到的injectedElements
中:
接下來,繼續(xù)執(zhí)行InjectionMetadata
的inject
方法,在其中遍歷所有需要注入的屬性的列表,遍歷調(diào)用AutowiredAnnotationBeanPostProcessor的inject
方法:
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { Field field = (Field) this.member; Object value; if (this.cached) { value = resolvedCachedArgument(beanName, this.cachedFieldValue); } else { DependencyDescriptor desc = new DependencyDescriptor(field, this.required); desc.setContainingClass(bean.getClass()); Set<String> autowiredBeanNames = new LinkedHashSet<>(1); Assert.state(beanFactory != null, "No BeanFactory available"); TypeConverter typeConverter = beanFactory.getTypeConverter(); try {//用beanFactory解決依賴 value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter); } //后面代碼省略...
這里創(chuàng)建了一個(gè)DependencyDescriptor
,用來維護(hù)注入屬性與它的容器類containingClass
的關(guān)系,里面最重要的就是存放了注入屬性的類型、名稱,以及containingClass
的類型等信息。
調(diào)用resolveDependency
方法,其中沒有做什么實(shí)質(zhì)性的工作,繼續(xù)調(diào)用了doResolveDependency
方法:
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor); try { Object shortcut = descriptor.resolveShortcut(this); if (shortcut != null) { return shortcut; } //依賴的屬性值的類型 Class<?> type = descriptor.getDependencyType(); Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor); if (value != null) { if (value instanceof String) { String strVal = resolveEmbeddedValue((String) value); BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null); value = evaluateBeanDefinitionString(strVal, bd); } TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); return (descriptor.getField() != null ? converter.convertIfNecessary(value, type, descriptor.getField()) : converter.convertIfNecessary(value, type, descriptor.getMethodParameter())); } Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter); if (multipleBeans != null) { return multipleBeans; } //把匹配的值和類型拿出來,放到一個(gè)map中 Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor); if (matchingBeans.isEmpty()) { if (isRequired(descriptor)) { raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor); } return null; } String autowiredBeanName; Object instanceCandidate; //如果有超過一個(gè)匹配的,可能會(huì)有錯(cuò)誤 if (matchingBeans.size() > 1) { autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor); if (autowiredBeanName == null) { if (isRequired(descriptor) || !indicatesMultipleBeans(type)) { return descriptor.resolveNotUnique(type, matchingBeans); } else { return null; } } instanceCandidate = matchingBeans.get(autowiredBeanName); } else { Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next(); autowiredBeanName = entry.getKey(); instanceCandidate = entry.getValue(); } if (autowiredBeanNames != null) { //把找到的bean的名字放到set中 autowiredBeanNames.add(autowiredBeanName); } if (instanceCandidate instanceof Class) { // 實(shí)際獲取注入的bean instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this); } Object result = instanceCandidate; if (result instanceof NullBean) { if (isRequired(descriptor)) { raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor); } result = null; } if (!ClassUtils.isAssignableValue(type, result)) { throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass()); } return result; } finally { ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint); } }
通過findAutowireCandidates
方法,獲取與注入屬性匹配的值和類型,放到一個(gè)Map當(dāng)中,再通過它的beanName
,調(diào)用resolveCandidate
方法,實(shí)際獲取注入的bean實(shí)例。這一操作底層調(diào)用的也是BeanFactory的getBean
方法。
回到inject
方法,使用反射將注入的bean實(shí)例賦值給屬性:
ReflectionUtils.makeAccessible(field); field.set(bean, value);
在執(zhí)行完populateBean
方法后,依賴的屬性已經(jīng)被注入成功了。
執(zhí)行回調(diào)方法及后置處理器
在bean實(shí)例化完成后,執(zhí)行各種回調(diào)和后置管理器方法:
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { //若bean實(shí)現(xiàn)了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware接口,執(zhí)行回調(diào)方法 invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { //執(zhí)行所有后置處理器的before方法 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { //執(zhí)行bean生命周期回調(diào)中的init-method //若bean實(shí)現(xiàn)了InitializingBean接口,執(zhí)行afterPropertiesSet方法 invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { //執(zhí)行所有后置處理器的after方法 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
具體執(zhí)行內(nèi)容:
- 1、若bean實(shí)現(xiàn)了
BeanNameAware
、BeanClassLoaderAware
、BeanFactoryAware
接口,執(zhí)行回調(diào)方法 - 2、執(zhí)行所有后置處理器的
postProcessBeforeInitialization
方法 - 3、執(zhí)行bean生命周期回調(diào)中的
init-method
,若bean實(shí)現(xiàn)了InitializingBean
接口,執(zhí)行afterPropertiesSet
方法 - 4、執(zhí)行所有后置處理器的
postProcessAfterInitialization
方法
在這一步完成后,bean的實(shí)例化過程全部結(jié)束。最后執(zhí)行一下refresh
方法中的finishRefresh
方法,進(jìn)行廣播事件等操作。到這,一個(gè)完整的AnnotationConfigApplicationContext
初始化就完成了。
到此這篇關(guān)于Spring源碼解析 Bean屬性填充的文章就介紹到這了,更多相關(guān)Spring Bean屬性填充內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章

java開發(fā)的工廠方法模式及抽象工廠驗(yàn)證示例

SpringBoot 文件或圖片上傳與下載功能的實(shí)現(xiàn)

SpringBoot創(chuàng)建WebService方法詳解

JAVA中的靜態(tài)代理、動(dòng)態(tài)代理以及CGLIB動(dòng)態(tài)代理總結(jié)

SrpingDruid數(shù)據(jù)源加密數(shù)據(jù)庫密碼的示例代碼