前言
在前面的doCreateBean方法中,我們了解到,populateBean是負(fù)責(zé)填充Bean實例屬性的。此時Bean中需要依賴注入的成員已經(jīng)在applyMergedBeanDefinitionPostProcessors中被對應(yīng)的后置處理器進(jìn)行了存儲,最終的成員被封裝到了AutowiredAnnotationBeanPostProcessor#injectionMetadataCache這個集合中.
1. Dependencies和Dependency Injection
很多人可能還不清除什么是依賴和依賴注入.這是理解Spring IoC的一個核心概念.下面簡單從代碼的角度談?wù)勈裁词且蕾嚭鸵蕾囎⑷?
- 一個簡單的MVC登陸入口
@RestController
@RequestMapping("/web")
public class UserController {
@Autowired
@Qualifier("normalUserService")
private UserService userService;
/**
* 用戶登陸入口
*/
@PostMapping("/login")
public void login(User user) {
userService.login(user);
}
}
軟件架構(gòu)設(shè)計原則中要求面向接口編程,為此MVC架構(gòu)中往往采取的是上面代碼展示的這種結(jié)構(gòu),
UserController依賴于UserService接口的實現(xiàn)類.此時,UserController就與UserService直接形成了依賴關(guān)系.
此時,如果沒有Spring,我們有三種方式去將UserService注入進(jìn)來:
- 每次調(diào)用login的時候,
new UserService();- 通過setter的方式進(jìn)行注入.即UserController中提供
setUserService(UserService userService).- 通過構(gòu)造方法進(jìn)行注入,
public UserController(UserService userService).其中,new的方式是耦合度較高的做法。所以在Spring中,提供了
構(gòu)造注入和setter注入的方式來落地IoC思想(Inversion of Control).
與用戶主動調(diào)用的方式不同,在Spring框架中,往往只需要聲明好依賴關(guān)系,框架就會自動生成好用戶需要的Java對象,這就是所謂的Bean.我們一般將UserController中去注入UserService這個過程稱為依賴注入,即專業(yè)術(shù)語上的DI(Dependency Injection).
2. 自動裝配
@Autowired注解和@Resource注解都是自動裝配的代表,思考一下,自動裝配大概是什么過程?
從前面的文章中我們學(xué)習(xí)了,Spring將Java對象中的信息抽象成了BeanDefinition,最后通過getBean方法來加載非延遲加載的單例Bean,每當(dāng)getBean裝配完一個Bean之后,就會添加到單例緩存中.
那么自動裝配的過程,就是按規(guī)則(如果指定)從容器中獲取到依賴的Bean,然后通過反射進(jìn)行賦值完成裝配的的過程.
3. populateBean的總體流程
-
激活I(lǐng)nstantiationAwareBeanPostProcessor后置處理器的InstantiationAwareBeanPostProcessor方法: 在實例化bean之后,Spring屬性填充之前執(zhí)行的鉤子方法,
這是在Spring的自動裝配開始之前對該bean實例執(zhí)行自定義字段注入的回調(diào),也是最后一次機(jī)會在自動裝配前修改Bean的屬性值。 - 解析依賴注入的方式,將屬性裝配到PropertyValues中: resolvedAutowireMode.
- 激活I(lǐng)nstantiationAwareBeanPostProcessor#postProcessProperties: 對@AutoWired標(biāo)記的屬性進(jìn)行依賴注入.
- 依賴檢查: checkDependencies.
- 將解析的值用BeanWrapper進(jìn)行包裝: applyPropertyValues.
3.1 InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation
- AbstractAutowireCapableBeanFactory#populateBean
// InstantiationAwareBeanPostProcessors最后一次進(jìn)行對bean的屬性修改
// 采用職責(zé)鏈的方式對所有實現(xiàn)了InstantiationAwareBeanPostProcessor的后置處理器調(diào)用.
// 直到某個InstantiationAwareBeanPostProcessor在postProcessAfterInstantiation中返回了false
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 如果返回了false,直接中斷,不進(jìn)行下面的操作
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
populateBean中,首先會經(jīng)過判空校驗,校驗通過后.
檢查用戶是否有注冊InstantiationAwareBeanPostProcessor,如果有,使用責(zé)任鏈模式激活這些后置器中的postProcessAfterInstantiation方法,如果某個后置處理器返回了false,那么Spring就不會執(zhí)行框架的自動裝配邏輯了.官方的建議是不建議去擴(kuò)展此后置處理器,而是推薦擴(kuò)展自BeanPostProcessor或從InstantiationAwareBeanPostProcessorAdapter派生.
3.2 根據(jù)注入方式解析屬性到PropertyValues
// 這里的pvs其實是一個MutablePropertyValues實例
// 提供對屬性的讀寫操作實現(xiàn),同時可以通過構(gòu)造函數(shù)實現(xiàn)深拷貝
// 獲取BeanDefinition里面為Bean設(shè)置的屬性值
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// 根據(jù)Bean配置的依賴注入方式完成注入,默認(rèn)是0,即不走以下邏輯
// 如果設(shè)置了相關(guān)的依賴裝配方式,會遍歷Bean的屬性,根據(jù)type或者name完成相應(yīng)注入
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
// 根據(jù)beanName進(jìn)行autowired自動裝配邏輯
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
// 根據(jù)Type進(jìn)行autowired自動裝配邏輯
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
- 首先從BeanDefinition中取出
propertyValues,具體的調(diào)用方法在AbstractBeanDefinition#getPropertyValues中,返回的類型為MutablePropertyValues.- 解析依賴裝配入的方式.在
AutowireCapableBeanFactory接口中聲明了5種依賴注入的方式:
| resolvedAutowireMode | 依賴注入方式 | 描述 |
|---|---|---|
| 0 | AUTOWIRE_NO | 沒有顯式配置上裝配的方式 |
| 1 | AUTOWIRE_BY_NAME | 按beanName進(jìn)行裝配 |
| 2 | AUTOWIRE_BY_TYPE | 按type進(jìn)行裝配 |
| 3 | AUTOWIRE_CONSTRUCTOR | 在構(gòu)造函數(shù)中進(jìn)行裝配 |
| 4 | AUTOWIRE_AUTODETECT | 通過內(nèi)省bean類確定適當(dāng)?shù)淖詣友b配策略,Spring已經(jīng)將其標(biāo)注為@Deprecated
|
一般以注解的形式,默認(rèn)都解析為0,也就是沒有顯式配置自動裝配策略.
什么情況會進(jìn)入if條件中的代碼塊,通常是在XML配置文件中顯式指定了autowired或者在Java配置類中@Bean上,聲明autowired.
簡單給個示例:
@Bean(autowire = Autowire.BY_NAME)
3.3 InstantiationAwareBeanPostProcessor#postProcessProperties
如果沒有顯式聲明自動裝配的方式(
@Autowired注解),那么就會使用到InstantiationAwareBeanPostProcessor這個后置處理器的postProcessProperties方法.
// 容器是否注冊了InstantiationAwareBeanPostProcessors
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 是否進(jìn)行依賴檢查,默認(rèn)為false
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 對@AutoWired標(biāo)記的屬性進(jìn)行依賴注入
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
// 對解析完未設(shè)置的屬性再進(jìn)行處理
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
- AutowiredAnnotationBeanPostProcessor#postProcessProperties
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 獲取指定類中被@Autowired注解標(biāo)記的metadata.
// metadata在實例化后的applyMergedBeanDefinitionPostProcessors中進(jìn)行了存儲
// 此時的findAutowiringMetadata是從injectionMetadataCache緩存中讀取metadata
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
// 對Bean的屬性進(jìn)行自動注入
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
在前面的doCreateBean中我們對
applyMergedBeanDefinitionPostProcessors進(jìn)行了分析,在它的postProcessMergedBeanDefinition中已經(jīng)調(diào)用了findAutowiringMetadata這個方法對Bean上被@Autowired標(biāo)記的成員進(jìn)行了存儲,此時已經(jīng)進(jìn)入到了屬性填充階段,從injectionMetadataCache這個緩存區(qū)即可獲取InjectionMetadata類型的metadata,即依賴注入的元數(shù)據(jù).
InjectionMetadata中提供了一個inject方法,執(zhí)行自動注入依賴的邏輯.
3.3.1 org.springframework.beans.factory.annotation.InjectionMetadata#inject
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectedElement> checkedElements = this.checkedElements;
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
for (InjectedElement element : elementsToIterate) {
if (logger.isTraceEnabled()) {
logger.trace("Processing injected element of bean '" + beanName + "': " + element);
}
// 調(diào)用InjectedElement#inject,這里是多態(tài)的實現(xiàn)
// @Autowired關(guān)注AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement.inject
element.inject(target, beanName, pvs);
}
}
}
這里邏輯比較清晰,查看當(dāng)前的
checkedElements是否為空,如果為空,解析injectedElements.然后遍歷對element執(zhí)行inject操作.
- AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
// 當(dāng)前存儲的需要注入的成員
Field field = (Field) this.member;
Object value;
// 如果該成員的值被緩存了,從緩存中獲取
if (this.cached) {
// 最終調(diào)用DefaultListableBeanFactory的resolveDependency
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
// 為該成員創(chuàng)建一個DependencyDescriptor.
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
// 設(shè)置當(dāng)前bean的Class
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
// 獲取類型轉(zhuǎn)換器
TypeConverter typeConverter = beanFactory.getTypeConverter();
try {
// 最終調(diào)用DefaultListableBeanFactory的resolveDependency
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
synchronized (this) {
// 如果成員變量的值沒有緩存
if (!this.cached) {
// 成員變量的值不為null,并且required==true
if (value != null || this.required) {
this.cachedFieldValue = desc;
// 注冊依賴關(guān)系
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
// 依賴對象類型和字段類型匹配,默認(rèn)按類型注入
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
this.cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
else {
this.cachedFieldValue = null;
}
this.cached = true;
}
}
}
if (value != null) {
ReflectionUtils.makeAccessible(field);
// 調(diào)用反射進(jìn)行賦值
field.set(bean, value);
}
}
}
OK,來到解析依賴的關(guān)鍵步驟了.
- 先嘗試從緩存中獲取該依賴對應(yīng)的Bean.
- 如果BeanFactory中沒有該依賴對應(yīng)的Bean.為該成員創(chuàng)建一個
DependencyDescriptor,然后調(diào)用beanFactory.resolveDependency來加載Bean.- 注冊Bean之間的依賴關(guān)系.
- 將獲取到的Bean調(diào)用反射進(jìn)行填充.
field.set(bean, value),注意在這一步之前,Spring對field的權(quán)限進(jìn)行了設(shè)置,field.setAccessible(true)其中,自動裝配的邏輯就封裝在了
beanFactory.resolveDependency中.繼續(xù)前進(jìn)一探究竟.
3.3.2 DefaultListableBeanFactory#resolveDependency
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
// 解析依賴
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
這里Spring會對依賴做一些適配,我們主要看
doResolveDependency這個解析依賴的方法.
- DefaultListableBeanFactory#doResolveDependency
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
// 從容器中獲取依賴,在debug環(huán)境下點進(jìn)去會發(fā)現(xiàn),會到達(dá)beanFactory.getBean()中
Object shortcut = descriptor.resolveShortcut(this);
// 如果可以從容器中獲取到bean,直接返回
if (shortcut != null) {
return shortcut;
}
Class<?> type = descriptor.getDependencyType();
// 處理@Value注解
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());
try {
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
}
catch (UnsupportedOperationException ex) {
// A custom TypeConverter which does not support TypeDescriptor resolution...
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
}
// 如果標(biāo)識@Autowired注解的成員變量是復(fù)合類型,如:數(shù)組、List、Map等.
// 從這里獲取@Autowired中的值
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
// 如果被@Autowired標(biāo)注的成員并非復(fù)合對象
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
// 如果找不到,校驗當(dāng)前是否標(biāo)注了required為true.
if (isRequired(descriptor)) {
// 如果@Autowired標(biāo)注了(required = true),但是無法匹配到相應(yīng)的bean,拋出NoSuchBeanDefinitionException異常
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
// 如果匹配到了不止一個Bean,看看是否標(biāo)注了@Primary和@Priority
if (matchingBeans.size() > 1) {
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
// 如果沒有聲明,則直接拋出NoUniqueBeanDefinitionException
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
// key為被依賴的候選者名稱,例如:UserController依賴UserService.
// 此時autowiredBeanName=userService
autowiredBeanName = entry.getKey();
// Class,先選舉,選舉結(jié)束之后再進(jìn)行實例化
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
if (instanceCandidate instanceof Class) {
// 將獲取到的候選者Class進(jìn)行g(shù)etBean
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);
}
}
這里的代碼邏輯就跟我們平時編程是息息相關(guān)的了。
- 調(diào)用
descriptor.resolveShortcut查看當(dāng)前工廠是否已經(jīng)加載過相同的Bean,如果是則直接返回.- 處理
@Value解析的邏輯.- 如果當(dāng)前注入的是復(fù)合對象,調(diào)用
resolveMultipleBeans.- 如果只是注入普通的Bean對象,查找符合條件的候選名單.返回一個Map.
為什么返回一個Map呢,這是因為一個接口可以有多個實現(xiàn)類,按照類型查找,就會把實現(xiàn)該接口的實現(xiàn)類返回.在應(yīng)對這種多個候選Bean的時候,Spring會去判斷是是否聲明了@Primary注解或者@Order注解來決定注入哪個Bean.如果沒有聲明,再判斷是否聲明了required=false),如果required為默認(rèn)的,則拋出NoUniqueBeanDefinitionException異常。- 匹配完候選名單后,對候選名單進(jìn)行
resolveCandidate操作,點進(jìn)去方法會發(fā)現(xiàn),其實是調(diào)用了beanFactory.getBean(beanName).
什么是復(fù)合對象?
Spring不僅僅只可以注入單一的Bean對象,還支持?jǐn)?shù)組、集合、Stream、Map等方式的注入.
3.3.3 如果Autowired按byType的方式無法挑選出最合適的Bean如何進(jìn)行降級處理
答案在
determineAutowireCandidate中,在通過byType的方式無法選出最合適的Bean后,Spring會用byName的方式對比出當(dāng)前屬性名與候選Bean名單中的candidateName是否匹配來做最終的處理.
- DefaultListableBeanFactory#determineAutowireCandidate
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
Class<?> requiredType = descriptor.getDependencyType();
// 根據(jù)@Primary注解標(biāo)簽來選擇最優(yōu)解
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
return primaryCandidate;
}
// 根據(jù)@Order、@Priority以及實現(xiàn)了Order接口的序號來最合適的Bean(序號越小越合適)進(jìn)行注入
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return priorityCandidate;
}
// Fallback
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateName = entry.getKey();
Object beanInstance = entry.getValue();
// 如果無法通過上面兩個方法找到最優(yōu)解的Bean:
// 如果類型已經(jīng)在resolvableDependencies中,直接返回已經(jīng)注冊的對象.
// 如果byType的方式找不到,嘗試使用byName的方式尋找依賴
// 如果屬性名稱和某個候選者的Bean名稱或者別名一致,則直接將該Bean返回
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
matchesBeanName(candidateName, descriptor.getDependencyName())) {
return candidateName;
}
}
return null;
}
假設(shè)
UserService有兩個實現(xiàn)類,VipUserService的beanName被主動聲明為vip,NormalUserService聲明為normal,那么你在Controller中可以這樣寫來注入VipUserService:
@Autowired
UserService vip;
4. 依賴檢查
Spring在最新的版本已經(jīng)不推薦使用,所以這里我們也不做重點講解.
5. 將解析的值用BeanWrapper進(jìn)行包裝-applyPropertyValues.
通過注解形式配置的Bean并不會往pvs中填充值,筆者在一些書上看到都是重點解析這個方法,目前Spring5.1的版本進(jìn)行debug未發(fā)現(xiàn)進(jìn)入到這個方法中,所以也不做詳細(xì)的講解。我更傾向于這是為了兼容XML的做法留下的方法.
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
if (pvs.isEmpty()) {
return;
}
if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
}
MutablePropertyValues mpvs = null;
List<PropertyValue> original;
if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues) pvs;
if (mpvs.isConverted()) {
// Shortcut: use the pre-converted values as-is.
try {
bw.setPropertyValues(mpvs);
return;
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
original = mpvs.getPropertyValueList();
}
else {
original = Arrays.asList(pvs.getPropertyValues());
}
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
// Create a deep copy, resolving any references for values.
List<PropertyValue> deepCopy = new ArrayList<>(original.size());
boolean resolveNecessary = false;
for (PropertyValue pv : original) {
if (pv.isConverted()) {
deepCopy.add(pv);
}
else {
String propertyName = pv.getName();
Object originalValue = pv.getValue();
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
Object convertedValue = resolvedValue;
boolean convertible = bw.isWritableProperty(propertyName) &&
!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
if (convertible) {
convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
}
// Possibly store converted value in merged bean definition,
// in order to avoid re-conversion for every created bean instance.
if (resolvedValue == originalValue) {
if (convertible) {
pv.setConvertedValue(convertedValue);
}
deepCopy.add(pv);
}
else if (convertible && originalValue instanceof TypedStringValue &&
!((TypedStringValue) originalValue).isDynamic() &&
!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
pv.setConvertedValue(convertedValue);
deepCopy.add(pv);
}
else {
resolveNecessary = true;
deepCopy.add(new PropertyValue(pv, convertedValue));
}
}
}
if (mpvs != null && !resolveNecessary) {
mpvs.setConverted();
}
// Set our (possibly massaged) deep copy.
try {
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
/**
* Convert the given value for the specified target property.
*/
@Nullable
private Object convertForProperty(
@Nullable Object value, String propertyName, BeanWrapper bw, TypeConverter converter) {
if (converter instanceof BeanWrapperImpl) {
return ((BeanWrapperImpl) converter).convertForProperty(value, propertyName);
}
else {
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
return converter.convertIfNecessary(value, pd.getPropertyType(), methodParam);
}
}
從XML中配置的<bean>將所有的屬性聲明為了字符串,因此在這里需要做一些類型的解析和強(qiáng)轉(zhuǎn).核心方法:
- 解析
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);- 注入
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
總結(jié)
- 注解驅(qū)動的Bean執(zhí)行屬性填充并不在
autowireByName和autowireByType中,而是在AutowiredAnnotationBeanPostProcessor這個后置處理器的postProcessProperties中. - 在做屬性填充時,如果當(dāng)前的Bean實例依賴的成員(另一個Bean)未被加載,會進(jìn)入選舉候選名單的邏輯中,進(jìn)行各種判斷后,選出最適合的Bean實例進(jìn)行
getBean操作. -
@Autowired在進(jìn)行自動裝配的過程中,默認(rèn)按照"byType"的方式進(jìn)行Bean加載,如果出現(xiàn)無法挑選出合適的Bean的情況,再將屬性名與候選Bean名單中的beanName進(jìn)行對比. - 正確地聲明
@Primary和Order等注解讓Bean在多態(tài)的選舉中優(yōu)選勝出. -
required=false可以讓程序在找不到Bean的時候不拋出異常,但是調(diào)用期間還是會報錯(緩兵之計),不建議這種使用. - XML的自動裝配模式與注解驅(qū)動的模式在代碼上是不同的分岔.