Spring源碼解析 Bean屬性填充
前言
在上一篇文章中,我們分析了Spring中Bean的實例化過程,在結尾我們知道了雖然bean的實例化完成了,但是其中的屬性還沒有被注入,今天我們就接著來分析屬性是如何被注入的。
屬性填充
實例化完成后,回到上面第3條的doCreateBean
方法中,看一下用BeanWrapper
產(chǎn)生的原生對象,里面dao
這個屬性還是null
值。
回歸一下之前的代碼,接下來要調用populateBean
方法進行屬性的填充:
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
方法獲得當前注冊的所有后置處理器,如果屬于InstantiationAwareBeanPostProcessor
類型,則調用它的postProcessPropertyValues
方法。通過遍歷,可以知道當前spring中存在7個后置處理器:
我們主要來看一下AutowiredAnnotationBeanPostProcessor
,因為它負責對添加了 @Autowired
、@Value
等注解的屬性進行依賴的填充。進入它的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ù),在它里面維護了一個Collection
,來存放所有需要注入的bean:
private final Collection<InjectedElement> injectedElements;
進入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í)行完這一步后,就把需要填充的屬性放進了剛才提到的injectedElements
中:
接下來,繼續(xù)執(zhí)行InjectionMetadata
的inject
方法,在其中遍歷所有需要注入的屬性的列表,遍歷調用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)建了一個DependencyDescriptor
,用來維護注入屬性與它的容器類containingClass
的關系,里面最重要的就是存放了注入屬性的類型、名稱,以及containingClass
的類型等信息。
調用resolveDependency
方法,其中沒有做什么實質性的工作,繼續(xù)調用了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; } //把匹配的值和類型拿出來,放到一個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; //如果有超過一個匹配的,可能會有錯誤 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) { // 實際獲取注入的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
方法,獲取與注入屬性匹配的值和類型,放到一個Map當中,再通過它的beanName
,調用resolveCandidate
方法,實際獲取注入的bean實例。這一操作底層調用的也是BeanFactory的getBean
方法。
回到inject
方法,使用反射將注入的bean實例賦值給屬性:
ReflectionUtils.makeAccessible(field); field.set(bean, value);
在執(zhí)行完populateBean
方法后,依賴的屬性已經(jīng)被注入成功了。
執(zhí)行回調方法及后置處理器
在bean實例化完成后,執(zhí)行各種回調和后置管理器方法:
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實現(xiàn)了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware接口,執(zhí)行回調方法 invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { //執(zhí)行所有后置處理器的before方法 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { //執(zhí)行bean生命周期回調中的init-method //若bean實現(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í)行內容:
- 1、若bean實現(xiàn)了
BeanNameAware
、BeanClassLoaderAware
、BeanFactoryAware
接口,執(zhí)行回調方法 - 2、執(zhí)行所有后置處理器的
postProcessBeforeInitialization
方法 - 3、執(zhí)行bean生命周期回調中的
init-method
,若bean實現(xiàn)了InitializingBean
接口,執(zhí)行afterPropertiesSet
方法 - 4、執(zhí)行所有后置處理器的
postProcessAfterInitialization
方法
在這一步完成后,bean的實例化過程全部結束。最后執(zhí)行一下refresh
方法中的finishRefresh
方法,進行廣播事件等操作。到這,一個完整的AnnotationConfigApplicationContext
初始化就完成了。
到此這篇關于Spring源碼解析 Bean屬性填充的文章就介紹到這了,更多相關Spring Bean屬性填充內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringBoot 文件或圖片上傳與下載功能的實現(xiàn)
這篇文章主要介紹了SpringBoot 文件或圖片上傳與下載功能的實現(xiàn),本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-02-02SpringBoot創(chuàng)建WebService方法詳解
這篇文章主要介紹了SpringBoot如何創(chuàng)建WebService,文中有詳細的實現(xiàn)步驟以及示例代碼,對學習或工作有一定的幫助,需要的朋友跟著小編一起來學習吧2023-05-05JAVA中的靜態(tài)代理、動態(tài)代理以及CGLIB動態(tài)代理總結
本篇文章主要介紹了JAVA中的靜態(tài)代理、動態(tài)代理以及CGLIB動態(tài)代理總結,具有一定的參考價值,有興趣的可以了解一下2017-08-08SrpingDruid數(shù)據(jù)源加密數(shù)據(jù)庫密碼的示例代碼
本篇文章主要介紹了SrpingDruid數(shù)據(jù)源加密數(shù)據(jù)庫密碼的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-10-10