SpringBoot深入理解 -- @AliasFor注解的作用
SpringBoot源碼解析 -- SpringBoot啟動(dòng)過程
SpringBoot源碼解析 -- AutoConfigure的實(shí)現(xiàn)原理
SpringBoot源碼解析 -- @ComponentScan的實(shí)現(xiàn)原理
SpringBoot源碼解析 -- @Value,@Autowired實(shí)現(xiàn)原理
SpringBoot源碼解析 -- Tomcat棍潘,SpringMVC啟動(dòng)
SpringBoot源碼解析 -- Logging渣锦,Environment啟動(dòng)
前面解析@ComponentScan實(shí)現(xiàn)原理的文章說了尝盼,Spring如何掃描@Component注解的Bean,但掃描的Bean如何注入屬性呢氮发?
我們都知道該功能主要使用@Value,@Autowired注解完成,這篇文章主要解析Spring中@Value,@Autowired實(shí)現(xiàn)原理酥艳。
源碼分析基于spring boot 2.1
前面解析Spring注入屬性過程的文章中,說過AbstractAutowireCapableBeanFactory#populateBean方法負(fù)責(zé)注入bean的屬性爬骤,其實(shí)@Value充石,@Autowired等注解也是在該方法處理。
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
...
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// #1
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
...
}
#1
調(diào)用InstantiationAwareBeanPostProcessor#postProcessProperties擴(kuò)展方法霞玄,這里處理@Value骤铃,@Autowired等注解。
在解析SpringBoot啟動(dòng)過程的文章中坷剧,說過了AutowiredAnnotationBeanPostProcessor負(fù)責(zé)處理@Value惰爬,@Autowired等注解。
(AutowiredAnnotationBeanPostProcessor是InstantiationAwareBeanPostProcessor的實(shí)現(xiàn)類)
AutowiredAnnotationBeanPostProcessor#postProcessProperties
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// #1
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
// #2
metadata.inject(bean, beanName, pvs);
}
...
return pvs;
}
#1
獲取Class中關(guān)于屬性注入相關(guān)注解的元數(shù)據(jù)
#2
完成屬性注入操作
AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata -> buildAutowiringMetadata
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>();
Class<?> targetClass = clazz;
do {
final LinkedList<InjectionMetadata.InjectedElement> currElements =
new LinkedList<InjectionMetadata.InjectedElement>();
ReflectionUtils.doWithLocalFields(targetClass, new ReflectionUtils.FieldCallback() {
@Override
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
// #1
AnnotationAttributes ann = findAutowiredAnnotation(field);
if (ann != null) {
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation is not supported on static fields: " + field);
}
return;
}
boolean required = determineRequiredStatus(ann);
currElements.add(new AutowiredFieldElement(field, required));
}
}
});
... // #2
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return new InjectionMetadata(clazz, elements);
}
#1
查找field是否有@Autowired惫企,@Value等注解
#2
查找method是否有@Autowired撕瞧,@Value等注解
InjectionMetadata#inject方法遍歷所有的InjectedElement,調(diào)用AutowiredMethodElement雅任,AutowiredFieldElement的inject方法风范,這里只關(guān)注AutowiredFieldElement#inject
InjectionMetadata#inject -> AutowiredFieldElement#inject
protected void inject(Object bean, String beanName, 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<String>(1);
TypeConverter typeConverter = beanFactory.getTypeConverter();
try {
// #1
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
...
}
if (value != null) {
// #2
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
#1
根據(jù)注解元數(shù)據(jù),解析屬性值
#2
將解析的結(jié)果值注入到bean
DefaultListableBeanFactory#resolveDependency -> DefaultListableBeanFactory#doResolveDependency
public Object doResolveDependency(DependencyDescriptor descriptor, String beanName,
Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
Class<?> type = descriptor.getDependencyType();
// #1
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
if (value instanceof String) {
// #2
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
value = evaluateBeanDefinitionString(strVal, bd);
}
//#3
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
// #4
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
// #5
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;
// #6
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) {
autowiredBeanNames.add(autowiredBeanName);
}
return (instanceCandidate instanceof Class ?
descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate);
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
#1
如果存在@Value注解沪么,獲取注解的value值
#2
解析@Value注解的值硼婿,如果這里使用占位符引用了配置文件,默認(rèn)使用PropertyPlaceholderConfigurer#PlaceholderResolvingStringValueResolver解析配置文件中的值禽车。
PropertyPlaceholderConfigurer是一個(gè)常用的BeanFactoryPostProcessor寇漫,它可以在Spring啟動(dòng)時(shí)刊殉,將Bean屬性配置的占位符解析為配置屬性的值
#3
默認(rèn)使用SimpleTypeConverter將配置值轉(zhuǎn)化為屬性要求的類型(例如屬性為int類型,則需要將String轉(zhuǎn)換為int類型)
這里最終也會(huì)復(fù)用TypeConverterDelegate#convertIfNecessary方法州胳。
#4
解析數(shù)組记焊、list、map等類型的依賴栓撞,使用對(duì)應(yīng)的TypeConverter處理
#5
處理@Autowire遍膜,找到候選的bean
#6
存在多個(gè)候選的bean,spring要按優(yōu)先級(jí)決定用哪個(gè)瓤湘,較復(fù)雜瓢颅,不深入。
DefaultListableBeanFactory#findAutowireCandidates
protected Map<String, Object> findAutowireCandidates(
String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
// #1
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
Map<String, Object> result = new LinkedHashMap<String, Object>(candidateNames.length);
// #2
for (Class<?> autowiringType : this.resolvableDependencies.keySet()) {
if (autowiringType.isAssignableFrom(requiredType)) {
Object autowiringValue = this.resolvableDependencies.get(autowiringType);
autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
if (requiredType.isInstance(autowiringValue)) {
result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
break;
}
}
}
//#3
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
...
return result;
}
#1
按類型查找spring上下文中所有的bean
#2
從當(dāng)前已存在的依賴關(guān)系中查找
#3
遍歷#1
步驟中找到的bean弛说,如果滿足Autowire要求挽懦,添加到結(jié)果
這里檢查候選類的類型是否匹配,是否滿足@Qualifier的要求木人,不繼續(xù)深入信柿,有興趣的同學(xué)自行閱讀源碼。
如果您覺得本文不錯(cuò)醒第,歡迎關(guān)注我的微信公眾號(hào)渔嚷,您的關(guān)注是我堅(jiān)持的動(dòng)力!