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方法重寫和super關(guān)鍵字實(shí)例詳解
這篇文章主要介紹了java方法重寫和super關(guān)鍵字實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-03-03
SpringBoot基于Redis實(shí)現(xiàn)token的在線續(xù)期的實(shí)踐
本文主要介紹了使用Redis實(shí)現(xiàn)JWT令牌在線續(xù)期的方案,通過在線續(xù)期token,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-12-12
java中l(wèi)ambda表達(dá)式簡(jiǎn)單用例
讓我們從最簡(jiǎn)單的例子開始,來學(xué)習(xí)如何對(duì)一個(gè)string列表進(jìn)行排序。我們首先使用Java 8之前的方法來實(shí)現(xiàn)2016-09-09
Spring Bean實(shí)例化實(shí)現(xiàn)過程解析
這篇文章主要介紹了Spring Bean實(shí)例化實(shí)現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02
Java調(diào)用計(jì)算機(jī)攝像頭拍照實(shí)現(xiàn)過程解析
這篇文章主要介紹了Java調(diào)用計(jì)算機(jī)攝像頭拍照實(shí)現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05
Spring框架應(yīng)用的權(quán)限控制系統(tǒng)詳解
在本篇文章里小編給大家整理的是關(guān)于基于Spring框架應(yīng)用的權(quán)限控制系統(tǒng)的研究和實(shí)現(xiàn),需要的朋友們可以學(xué)習(xí)下。2019-08-08

