文章目录
(一)序言
在spring源码分析加载bean之doGetBean②分析里面doCreateBean中简单提到了populateBean属性注入,本文将对属性注入进行详细分析,笔者如有分析错误,还请及时指出。
(二)bean属性注入:populateBean
1、属性注入代码逻辑:populateBean
AbstractAutowireCapableBeanFactory类中的doCreateBean方法中实例化bean完成后,紧接着执行populateBean(beanName,mbd,instanceWrapper);进行属性注入,populateBean具体代码如下:
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {// 实例化的对象是空且有任何属性则抛出异常
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
} else {
// 实例化的对象是空且没有任何属性则直接结束
return;
}
}
/**
* 在属性设置前执行InstantiationAwareBeanPostProcessors后置处理器,调用postProcessAfterInstantiation方法可以加工bean
* 不同的是,在createBean中已经调用过InstantiationAwareBeanPostProcessors->postProcessBeforeInstantiation方法
*/
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
//bean如果实现了InstantiationAwareBeanPostProcessor,则会执行重写的postProcessAfterInstantiation方法
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
//bean自动注入的方式:按名称注入和按类型注入
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 根据名称自动注入
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 根据类型自动注入
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
//是否有InstantiationAwareBeanPostProcessor后置处理器
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
//是否需要检查依赖
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
//执行后置处理器InstantiationAwareBeanPostProcessor中的postProcessProperties方法和postProcessPropertyValues方法
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
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;
}
}
}
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
//依赖检查
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if (pvs != null) {
//将属性注入到bean中
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
2、属性注入整体流程
(1)是否需要执行InstantiationAwareBeanPostProcessor后置处理器中的postProcessorAfterInstantiation方法,主要是用户自行扩展且可以控制bean注入是否需要继续属性填充;
(2)根据注入类型,分为按名称注入和按类型注入,将需要依赖的bean提取存储到MutablePropertyValues
newPvs对象中的propertyValueList变量中,具体类型是PropertyValue;
(3)InstantiationAwareBeanPostProcessor后置处理器中的postProcessProperties和postProcessPropertyValues方法,在属性注入前对注入的属性进行再次处理;
(4)将PropertyValues中的属性都填充到BeanWrapper。
(三)属性注入中的核心方法
1、按名称注入:autowireByName
获取当前bean中的注入属性,并通过属性的bean名称去加载bean,最后将属性注册,代码逻辑如下:
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
//寻找bw中需要被注入的bean属性
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
//检查缓存中是否已包含属性bean
if (containsBean(propertyName)) {
Object bean = getBean(propertyName);//去加载bean(递归)
pvs.add(propertyName, bean);//将bean属性存储到pvs
//注册依赖:Map<String, Set<String>>类型的dependentBeanMap和dependenciesForBeanMap变量中
registerDependentBean(propertyName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Added autowiring by name from bean name '" + beanName +
"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
}
}else {
if (logger.isTraceEnabled()) {
logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
"' by name: no matching bean found");
}
}
}
}
2、按类型注入:autowireByType(较复杂)
先获取属性bean,然后对需要依赖注入的属性bean获取set方法,紧接着对属性bean进行类型匹配(最复杂、核心),将所有需要被依赖注入的属性进行注册,代码如下:
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
TypeConverter converter = getCustomTypeConverter();//自定义的类型转换器
if (converter == null) {
converter = bw;
}
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
//寻找需要依赖注入的bean属性
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
try {
//获取属性描述符
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
if (Object.class != pd.getPropertyType()) {
//获取属性bean的set方法
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
//将bean属性类型匹配到的值存储到autowiredBeanNames中(核心)
//这里的返回值是真正的需要注入的属性,autowiredBeanNames是需要注入的属性(可能是集合)的names
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
pvs.add(propertyName, autowiredArgument);//添加待注入的bean列表中
}
for (String autowiredBeanName : autowiredBeanNames) {
registerDependentBean(autowiredBeanName, beanName);//注册依赖
if (logger.isTraceEnabled()) {
logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
propertyName + "' to bean named '" + autowiredBeanName + "'");
}
}
autowiredBeanNames.clear();//释放
}
}catch (BeansException ex) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
}
}
}
3、匹配类型bean:(do)resolveDependency(doXX核心)
(1)@Autowired注解是在AutowiredAnnotationBeanPostProcessor中注入时会被调用;
(2)ConstructorResolver->autowireConstructor在resolveAutowiredArgument(methodParam,beanName,autowiredBeanNames,converter,fallback);代码执行过程时,也会调用resolveDependency方法。
DefaultListableBeanFactory->resolveDependency代码如下:
public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName,
Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
//处理不同的bean属性类型
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 {
//处理懒加载的bean,若是,则创建代理对象,否则将执行通用类型的依赖处理
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
//处理通用类型的依赖,熟悉的doXX方法
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
Spring开发常用依赖注入类型由DefaultListableBeanFactory->doResolveDependency掌控,其主要核心步骤如下:
(1)resolveEmbeddedValue对占位符的替换即@Value注解的${};
(2)解析依赖属性即流stream、数组Array、集合Collection和Map类型;
(3)spring根据三大顺序(@Primary、@Priority和fallback匹配)从多个实例中选择一个作为将要注入的实例;
(4)检查匹配出来的实例与实际类型是否相符合。
DefaultListableBeanFactory->doResolveDependency具体代码如下:
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
//利用重写了ThreadLocal的NamedThreadLocal来设置当前注入点,提高安全性,进行隔离
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
/**
* 仅ShortcutDependencyDescriptor重写了resolveShortcut方法且在AutowiredFieldElement、AutowiredMethodElement->inject使用到,
* 只有解析@Autowired、@Value注解的元素才会用到,作用是避免重复解析、使用缓存存储,提升注入性能
*/
Object shortcut = descriptor.resolveShortcut(this);
//shortcut这个值实际上是由beanFactory.getBean(this.shortcut, this.requiredType)加载获取的
if (shortcut != null) {
return shortcut;
}
//缓存中没有该bean,则开始执行类型匹配逻辑
Class<?> type = descriptor.getDependencyType();
//用于获取@Value注解的值,如@Value(value = "${xx.yy}")
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
//此时的value是${xx.yy}这个值,spring的SPEL表达式未被替换
if (value != null) {
if (value instanceof String) {
/**
* resolveEmbeddedValue该方法很复杂,找对方法实现类就简单,核心思想就是替换占位符${}
* (1)AbstractBeanFactory中的resolveEmbeddedValue方法
* (2)PropertySourcesPlaceholderConfigurer->processProperties中的valueResolver匿名内部方法->resolveRequiredPlaceholders
* (3)AbstractPropertyResolver->createPlaceholderHelper创建正则表达式替换,placeholderPrefix前缀和placeholderSuffix后缀
* (4)AbstractPropertyResolver->doResolvePlaceholders执行正则表达式进行占位符替换
*/
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
//解析Spring中的SPEL表达式
value = evaluateBeanDefinitionString(strVal, bd);
}
//获取类型转换器
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
//将解析出来的bean,转换为type类型
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()));
}
}
//解析依赖的是流stream、数组Array、集合Collection和Map类型的属性
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
//查找所有type类型的实例,将其使用键值对存储在matchingBeans变量中,String为:实例对应的beanName,Object为实例
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
//注解中添加了required=true时,若没找到则抛异常
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
//matchingBeans大于1,说明Spring中找到了多个该type类型的实例
if (matchingBeans.size() > 1) {
/**
* spring从多个实例中按照一定的顺序选择一个作为注入的实例
* (1)被标识为@primary的bean
* (2)挑标识为@Priority且优先级最高的bean。可以不标识,一旦标识,不允许同一优先级的存在
* (3)fallback依赖的名称与matchingBeans中任意一Key匹配
*/
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
//在选择实例时为空且非集合类的bean匹配到多个将报非唯一性错误
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}else {
return null;
}
}
//从matchingBeans中获取对应的类型匹配结果中的实例
instanceCandidate = matchingBeans.get(autowiredBeanName);
}else {
//程序走到这里代表只有唯一的一个type实例
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
if (instanceCandidate instanceof Class) {
// 确保instanceCandidate是bean的实例,前面matchingBeans中的Object有可能是实例或类类对象
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
//该依赖属性是NullBean且required=true未找到时报错
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
//匹配到的类型和实际type是否想匹配
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;
}finally {
//更新注入点
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
4、依赖注入:applyPropertyValues
applyPropertyValues是populateBean属性注入的最后一步,也是前面一系列选择实例、后置处理器对属性进行加工后,将属性存储,到applyPropertyValues方法才是使用该属性进行注入,具体代码如下:
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;
//populateBean方法中如果正常获取到的属性是存储在MutablePropertyValues中,如果存在则直接注入
if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues) pvs;
if (mpvs.isConverted()) {//是否被转换过
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;
}
//创建一个BeanDefinition的处理器
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
//创建一个变量进行深拷贝
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();
if (originalValue == AutowiredPropertyMarker.INSTANCE) {
Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();
if (writeMethod == null) {
throw new IllegalArgumentException("Autowire marker for property without write method: " + pv);
}
originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);
}
//对属性进行转换处理
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);
}
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();//设置已被转换过
}
//将深拷贝过来的数据封装,防止前面的逻辑不满足,未注入时的保底手段
try {
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
(四)属性注入总结
(1)InstantiationAwareBeanPostProcessors后置器的postProcessAfterInstantiation实例化后方法控制bean是否需要进行后续属性注入;
(2)解析依赖属性并根据配置采用哪种注入方式,XML中可使用default-autowire="byName"指定按名称AUTOWIRE_BY_NAME或按类型AUTOWIRE_BY_TYPE注入;
(3)InstantiationAwareBeanPostProcessor后置器的postProcessPropertyValues方法对依赖属性进行注入前处理;
(4)applyPropertyValues注入属性,前面将属性处理、加工得到的属性注入到bean的依赖属性中。
说明:
(1)按名称注入AUTOWIRE_BY_NAME:主要就是从Spring中加载bean即getBean方法;
(2)按类型注入AUTOWIRE_BY_TYPE:主要是处理@Value注解以及配置的property、自动装配@Autowired的实现类提取注入,DefaultListableBeanFactory->doResolveDependency具体核心点如下:
(1)resolveEmbeddedValue对占位符的替换即@Value注解的${};
(2)解析依赖属性即流stream、数组Array、集合Collection和Map类型;
(3)spring根据三大顺序(@Primary、@Priority和fallback匹配)从多个实例中选择一个作为将要注入的实例;
(4)检查匹配出来的实例与实际类型是否相符合。