populate()依赖注入
继续之章节的doCreateBean()方法第四流程,对bean进行依赖注入,测试用例:
<bean id="book" class="com.myProject.Myspring.Book"/>
<bean id="user" class="com.myProject.Myspring.User">
<property name="book" ref="book"/>
</bean>
populate()核心代码:
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
...检查
//获取 配置的 属性 对应上方xml中的Property
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
//测试 demo中,返回的是0,所以下面的方法直接跳过
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
//深克隆
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
//注入属性 通过name
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 注入属性 通过type
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
//同样 测试demo中, 两个都是false
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
... 一大堆 检查操作
}
if (pvs != null) { //真正 依赖注入的地方 【入】
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
测试demo,从获得pvs开始,下面就没有调用什么方法,可以直接走到最核心的方法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;
if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues) pvs;
if (mpvs.isConverted()) { //默认是false 含义:属性值是否转化
// 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);
}
} //走这里 上面的if略过 获取属性值对象的原始类型值
original = mpvs.getPropertyValueList();
}
else {
original = Arrays.asList(pvs.getPropertyValues());
}
//根据用户自定义的类型转换 ,没有定义就为null
TypeConverter converter = getCustomTypeConverter();
if (converter == null) { //进
converter = bw;
}
//创建一个bean定义属性值解析器,将Bean定义中的属性值解析为bean实例对象的实际值
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(); //----- originalValue -> resolvedValue
//转换属性值,例如将引用转换为IOC容器中实例化的对象【引用】
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
//转换之后的 属性值
Object convertedValue = resolvedValue;
boolean convertible = bw.isWritableProperty(propertyName) &&
!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
if (convertible) {//true
convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
}
//存储转换后的属性值,避免每次属性注入时的转换工作
if (resolvedValue == originalValue) {//false
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. 进行属性的依赖注入
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
该方法主要分为两种情况:
1.属性值不需要强制转换,不需要解析属性值,直接进行依赖注入
2.属性值类型需要强制转换,如对其他对象的引用等,首先需要解析属性值(demo中,依赖的是一个对象,而不是基础int数据,所以需要解析属性值,从ioc容器中获得引用),然后再进行依赖注入。
首先我们探讨BeanDefinitionValueResolver类的resolveValueIfNecessary()方法:该方法内容很长
public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
//对引用类型的属性进行解析
if (value instanceof RuntimeBeanReference) {
RuntimeBeanReference ref = (RuntimeBeanReference) value;
return resolveReference(argName, ref); //【入】
} //对引用容器中另外一个bean名称的属性进行解析
else if (value instanceof RuntimeBeanNameReference) {
....
} //对bean类型属性的解析,主要是指bean中的内部类
else if (value instanceof BeanDefinitionHolder) {
BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;
return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
}
else if (value instanceof BeanDefinition) {
}//对集合数组类型的属性进行解析
else if (value instanceof ManagedArray) {
// May need to resolve contained runtime references.
ManagedArray array = (ManagedArray) value; //获取数组的类型
Class<?> elementType = array.resolvedElementType;
if (elementType == null) { //获取数组元素的类型
String elementTypeName = array.getElementTypeName();
if (StringUtils.hasText(elementTypeName)) {
try { //使用反射创建指定类型的对象
elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());
array.resolvedElementType = elementType;
}
catch (Throwable ex) {
// Improve the message by showing the context.
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Error resolving array type for " + argName, ex);
}
}
else { //没有获取到数组的类型,也没有获取到数组元数的类型,直接设置为Object
elementType = Object.class;
}
}//创建指定类型的数组
return resolveManagedArray(argName, (List<?>) value, elementType);
} //解析list类型的属性值
else if (value instanceof ManagedList) {
}
else if (value instanceof ManagedSet) {
}
else if (value instanceof ManagedMap) {
}
else if (value instanceof ManagedProperties) {
}
else if (value instanceof TypedStringValue) {
}
else if (value instanceof NullBean) {
return null;
}
else {
return evaluate(value);
}
}
我们的测试demo是一个普通的引用类型,所以我们调用第一个If里面的resolveReference()方法:
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
try {
Object bean;
String refName = ref.getBeanName(); //获得引用bean名称
refName = String.valueOf(doEvaluate(refName));
//如果引用的对象在父类容器中,则从父类容器中获取指定的引用对象
if (ref.isToParent()) {
if (this.beanFactory.getParentBeanFactory() == null) {throw }
bean = this.beanFactory.getParentBeanFactory().getBean(refName);
}
//从当前的容器中获取指定的引用bean对象,如果指定的bean没有实例化,则会递归触发引用bean的初始化和依赖注入
else {
bean = this.beanFactory.getBean(refName);
this.beanFactory.registerDependentBean(refName, this.beanName);
}
if (bean instanceof NullBean) {
bean = null;
}
return bean;
}
}
解析出来需要的属性之后,我们就开始依赖注入,AbstractPropertyAccessor类的setPropertyValues()方法:
public void setPropertyValues(PropertyValues pvs) throws BeansException {
setPropertyValues(pvs, false, false);
}
public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid) {
List<PropertyValue> propertyValues = (pvs instanceof MutablePropertyValues ?
((MutablePropertyValues) pvs).getPropertyValueList() : Arrays.asList(pvs.getPropertyValues()));
for (PropertyValue pv : propertyValues) {
setPropertyValue(pv);
}
}
最后,各种setPropertyValue()方法,来到AbstractNestablePropertyAccessor类的setPropertyValue(token,pv)方法中:
public void setPropertyValue(PropertyValue pv) throws BeansException {
PropertyTokenHolder tokens = (PropertyTokenHolder) pv.resolvedTokens;
if (tokens == null) {
String propertyName = pv.getName();
AbstractNestablePropertyAccessor nestedPa;
try {
nestedPa = getPropertyAccessorForPropertyPath(propertyName); //BeanWrapperImpl实例
}
tokens = getPropertyNameTokens(getFinalPath(nestedPa, propertyName)); //this
if (nestedPa == this) { //true
pv.getOriginalPropertyValue().resolvedTokens = tokens;
}
nestedPa.setPropertyValue(tokens, pv); //【入】
}
else {
setPropertyValue(tokens, pv);
}
}
protected void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) {
if (tokens.keys != null) {
processKeyedProperty(tokens, pv);
}
else {
processLocalProperty(tokens, pv);
}
}
对于我们的测试demo,走的是else,首先看一下:processKeyedProperty()方法:
private void processKeyedProperty(PropertyTokenHolder tokens, PropertyValue pv) {
//调用属性的get()方法,获取属性值
Object propValue = getPropertyHoldingValue(tokens); //【入】
PropertyHandler ph = getLocalPropertyHandler(tokens.actualName);
String lastKey = tokens.keys[tokens.keys.length - 1];
//注入array类型的属性值
if (propValue.getClass().isArray()) {
Class<?> requiredType = propValue.getClass().getComponentType();
int arrayIndex = Integer.parseInt(lastKey);
Object oldValue = null;
try {
if (isExtractOldValueForEditor() && arrayIndex < Array.getLength(propValue)) {
oldValue = Array.get(propValue, arrayIndex);
}
Object convertedValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(),
requiredType, ph.nested(tokens.keys.length));
int length = Array.getLength(propValue);
if (arrayIndex >= length && arrayIndex < this.autoGrowCollectionLimit) {
Class<?> componentType = propValue.getClass().getComponentType();
Object newArray = Array.newInstance(componentType, arrayIndex + 1);
System.arraycopy(propValue, 0, newArray, 0, length);
setPropertyValue(tokens.actualName, newArray);
propValue = getPropertyValue(tokens.actualName);
}
Array.set(propValue, arrayIndex, convertedValue);
}
}
//注入list类型的属性值
else if (propValue instanceof List) {
}
//注入map类型的属性值
else if (propValue instanceof Map) {
}
else {throw }
}
第二个:processLocalProperty()方法:
private void processLocalProperty(PropertyTokenHolder tokens, PropertyValue pv) {
PropertyHandler ph = getLocalPropertyHandler(tokens.actualName);
Object oldValue = null;
try {
Object originalValue = pv.getValue();
Object valueToApply = originalValue;
if (!Boolean.FALSE.equals(pv.conversionNecessary)) {
if (pv.isConverted()) {
valueToApply = pv.getConvertedValue();
}
else {
if (isExtractOldValueForEditor() && ph.isReadable()) { //false
try {
oldValue = ph.getValue();
}
} //
valueToApply = convertForProperty(
tokens.canonicalName, oldValue, originalValue, ph.toTypeDescriptor());
}
pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);
}
ph.setValue(valueToApply); //【注入】
}
}
到此,依赖注入完成,还有一些细节,可以继续深入探讨。
紧接着,bean初始化 位于AbstractAutowireCapableBeanFactory类的initializeBean()方法,这个和spring AOP有关,所以我们在后面aop章节介绍
第六流程:如果是单例模式的,需要缓存下来
if (earlySingletonExposure) {
//获取指定名称的 已注册的 单列模式的 bean对象
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) { //demo走这里
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
....
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
到这里,bean的create()结束,回到AbstractBeanFactory类的doGetbean()方法:
2.2 原型模式bean
回到AbstractBeanFactory类的doGetBean()方法中,继续我们的探索:
else if (mbd.isPrototype()) {
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args); //【入】
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
区别于单例模式,原型模式,多了before和after两个操作,都是针对属性的,中间的createBean()方法和单例模式的createBean()方法相同,所以这里就不继续展开了,我们看一下前置处理:
protected void beforePrototypeCreation(String beanName) {
Object curVal = this.prototypesCurrentlyInCreation.get();
if (curVal == null) {
this.prototypesCurrentlyInCreation.set(beanName); //主要是这个操作
}
else if (curVal instanceof String) {
Set<String> beanNameSet = new HashSet<>(2);
beanNameSet.add((String) curVal);
beanNameSet.add(beanName);
this.prototypesCurrentlyInCreation.set(beanNameSet);
}
else {
Set<String> beanNameSet = (Set<String>) curVal;
beanNameSet.add(beanName);
}
}
主要就是设置了一个值,其他没有动手。