在之前的 Spring源码剖析——核心IOC容器原理这篇文章中,已经详细介绍了在spring当中我们配置的Bean是怎样被Spring解析和管理的,我们配置的那些Bean经过 载入 、解析 和 注册 这三个过程后,在框架内部被抽象封装成BeanDefinition这种类型,最终所有的BeanDefinition交由BeanFactory当中的definitionMap统一管理起来(如果对该过程还不是很清楚可以先看之前的文章)。走到这一步,Spring还不能提供给我们一个完整可用的Bean,因为虽然所有的Bean已经在Spring经过解析和转化过程被集中组织起来,但此时这些BeanDefinition对象都是彼此分离的,并没有建立起依赖关系,也就是我们常说的 依赖注入 还没有发生。今天我们就来研究一下Spring中依赖注入的实现原理是怎样的。
依赖注入介绍
在分析原理之前我们先回顾下依赖注入的概念:
我们常提起的依赖注入(Dependency Injection)和控制反转(Inversion of Control)是同一个概念。具体含义是:当某个角色(可能是一个Java实例,调用者)需要另一个角色(另一个Java实例,被调用者)的协助时,在 传统的程序设计过程中,通常由调用者来创建被调用者的实例。但在Spring里,创建被调用者的工作不再由调用者来完成,因此称为控制反转;创建被调用者 实例的工作通常由Spring容器来完成,然后注入调用者,因此也称为依赖注入。
其实简单的说,依赖注入起到的作用就是讲对象之间的依赖关系从原先的代码中解耦出来,通过配置文件或注解等方式加上Spring框架的处理让我们对依赖关系灵活集中的进行管理。
源码剖析
之前的文章分析到了调用getBean获得Bean对象之前的步骤,而我们调用getBean后获得已经是完成依赖关系注入的完整Bean对象,所以完成依赖注入的奥秘就发生在getBean当中,要分析我们便从getBean这个入口开始吧。
getBean触发的依赖注入
先看看 getBean() 方法的源码,方法的实现是在 AbstractBeanFactory.java 中
getBean方法
@Override
public Object
getBean(String name)
throws BeansException {
return doGetBean(name,
null,
null,
false);
}
@Override
public <T> T
getBean(String name, Class<T> requiredType)
throws BeansException {
return doGetBean(name, requiredType,
null,
false);
}
@Override
public Object
getBean(String name, Object... args)
throws BeansException {
return doGetBean(name,
null, args,
false);
}
public <T> T
getBean(String name, Class<T> requiredType, Object... args)
throws BeansException {
return doGetBean(name, requiredType, args,
false);
}
12345678910111213141516171819202122
12345678910111213141516171819202122
几个重载的getBean方法的实现都调用了 doGetBean 这个方法,继续看 doGetBean()
doGetBean方法
protected <T> T
doGetBean(
final String name,
final Class<T> requiredType,
final Object[] args,
boolean typeCheckOnly)
throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
Object sharedInstance = getSingleton(beanName);
if (sharedInstance !=
null && args ==
null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug(
"Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug(
"Returning cached instance of singleton bean '" + beanName +
"'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName,
null);
}
else {
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory !=
null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (args !=
null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
String[] dependsOn = mbd.getDependsOn();
if (dependsOn !=
null) {
for (String dependsOnBean : dependsOn) {
if (isDependent(beanName, dependsOnBean)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName +
"' and '" + dependsOnBean +
"'");
}
registerDependentBean(dependsOnBean, beanName);
getBean(dependsOnBean);
}
}
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName,
new ObjectFactory<Object>() {
@Override
public Object
getObject()
throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
Object prototypeInstance =
null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
final Scope scope =
this.scopes.get(scopeName);
if (scope ==
null) {
throw new IllegalStateException(
"No Scope registered for scope name '" + scopeName +
"'");
}
try {
Object scopedInstance = scope.get(beanName,
new ObjectFactory<Object>() {
@Override
public Object
getObject()
throws BeansException {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName +
"' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
if (requiredType !=
null && bean !=
null && !requiredType.isAssignableFrom(bean.getClass())) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug(
"Failed to convert bean '" + name +
"' to required type [" +
ClassUtils.getQualifiedName(requiredType) +
"]", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
getBean是依赖注入的起点,之后会调用createBean,下面我们分析createBean的代码。
创建完整Bean的流程
createBean() 的实现是在 AbstractAutowireCapableBeanFactory 当中
creaBean方法
protected Object
createBean(String beanName, RootBeanDefinition mbd, Object[] args)
throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug(
"Creating instance of bean '" + beanName +
"'");
}
RootBeanDefinition mbdToUse = mbd;
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass !=
null && !mbd.hasBeanClass() && mbd.getBeanClassName() !=
null) {
mbdToUse =
new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName,
"Validation of method overrides failed", ex);
}
try {
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean !=
null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug(
"Finished creating instance of bean '" + beanName +
"'");
}
return beanInstance;
}
1234567891011121314151617181920212223242526272829303132333435363738
1234567891011121314151617181920212223242526272829303132333435363738
doCreateBean方法
protected Object
doCreateBean(
final String beanName,
final RootBeanDefinition mbd,
final Object[] args) {
BeanWrapper instanceWrapper =
null;
if (mbd.isSingleton()) {
instanceWrapper =
this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper ==
null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper !=
null ? instanceWrapper.getWrappedInstance() :
null);
Class<?> beanType = (instanceWrapper !=
null ? instanceWrapper.getWrappedClass() :
null);
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
mbd.postProcessed =
true;
}
}
boolean earlySingletonExposure = (mbd.isSingleton() &&
this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug(
"Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName,
new ObjectFactory<Object>() {
@Override
public Object
getObject()
throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject !=
null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
catch (Throwable ex) {
if (ex
instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Initialization of bean failed", ex);
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName,
false);
if (earlySingletonReference !=
null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!
this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans =
new LinkedHashSet<String>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName +
"' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Invalid destruction signature", ex);
}
return exposedObject;
}
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
看了上面的代码后,我们应该重点关注 createBeanInstance() 和 populateBean() 这两个方法。其中,createBeanInstance方法生成了Bean所包含的Java对象,代码如下
createBeanInstance方法
protected BeanWrapper
createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
Class<?> beanClass = resolveBeanClass(mbd, beanName);
if (beanClass !=
null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
if (mbd.getFactoryMethodName() !=
null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
boolean resolved =
false;
boolean autowireNecessary =
false;
if (args ==
null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod !=
null) {
resolved =
true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd,
null,
null);
}
else {
return instantiateBean(beanName, mbd);
}
}
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors !=
null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
return instantiateBean(beanName, mbd);
}
123456789101112131415161718192021222324252627282930313233343536373839404142434445
123456789101112131415161718192021222324252627282930313233343536373839404142434445
跟随上面的步伐,上面实例化的时候调用了instantiateBean方法,该方法代码如下:
instantiateBean方法
protected BeanWrapper
instantiateBean(
final String beanName,
final RootBeanDefinition mbd) {
try {
Object beanInstance;
final BeanFactory parent =
this;
if (System.getSecurityManager() !=
null) {
beanInstance = AccessController.doPrivileged(
new PrivilegedAction<Object>() {
@Override
public Object
run() {
return getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
}, getAccessControlContext());
}
else {
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
BeanWrapper bw =
new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Instantiation of bean failed", ex);
}
}
1234567891011121314151617181920212223
1234567891011121314151617181920212223
我们重点关注 getInstantiationStrategy() 这个方法,可以看到instantiateBean方法的功能实现是通过调用getInstantiationStrategy().instantiate方法实现的。 getInstantiationStrategy 方法的作用是获得实例化的策略对象,也就是指通过哪种方案进行实例化的过程。继续跟踪下去我们可以发现,Spring当中提供了两种实例化方案: BeanUtils 和 Cglib 方式。BeanUtils实现机制是通过Java的反射机制,Cglib是一个第三方类库采用的是一种字节码加强方式机制。 Spring中采用的默认实例化策略是Cglib。 分析到这里我们已经知道了实例化Bean对象的流程,现在已经是万事具备,只欠东风,就剩下对这些建立好的Bean对象建立联系了。
依赖关系的处理
我们要分析依赖关系是怎样注入到Bean对象当中,就需要回到前面的 populateBean() 方法,这个方法实现是在 AbstractAutowireCapableBeanFactory中
populateBean方法
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues();
if (bw ==
null) {
if (!pvs.isEmpty()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName,
"Cannot apply property values to null instance");
}
else {
return;
}
}
boolean continueWithPropertyPopulation =
true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp
instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation =
false;
break;
}
}
}
}
if (!continueWithPropertyPopulation) {
return;
}
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs =
new MutablePropertyValues(pvs);
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp
instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs ==
null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
applyPropertyValues(beanName, mbd, bw, pvs);
}
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
我们接着看 applyPropertyValues() 这个方法,了解具体的对属性解析然后注入的过程
applyPropertyValues方法
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
if (pvs ==
null || pvs.isEmpty()) {
return;
}
MutablePropertyValues mpvs =
null;
List<PropertyValue> original;
if (System.getSecurityManager() !=
null) {
if (bw
instanceof BeanWrapperImpl) {
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
}
}
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;
}
BeanDefinitionValueResolver valueResolver =
new BeanDefinitionValueResolver(
this, beanName, mbd, converter);
List<PropertyValue> deepCopy =
new ArrayList<PropertyValue>(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);
}
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);
}
}
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
上面的代码中通过 BeanDefinitionResolver 来对BeanDefinition进行解析,我们可以看下该上面解析过程中调用的主要处理方法 resolveValueIfNecessary()。
resolveValueIfNecessary方法
public Object
resolveValueIfNecessary(Object argName, Object value) {
if (value
instanceof RuntimeBeanReference) {
RuntimeBeanReference ref = (RuntimeBeanReference) value;
return resolveReference(argName, ref);
}
else if (value
instanceof RuntimeBeanNameReference) {
String refName = ((RuntimeBeanNameReference) value).getBeanName();
refName = String.valueOf(doEvaluate(refName));
if (!
this.beanFactory.containsBean(refName)) {
throw new BeanDefinitionStoreException(
"Invalid bean name '" + refName +
"' in bean reference for " + argName);
}
return refName;
}
else if (value
instanceof BeanDefinitionHolder) {
BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;
return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
}
else if (value
instanceof BeanDefinition) {
BeanDefinition bd = (BeanDefinition) value;
String innerBeanName =
"(inner bean)" + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR +
ObjectUtils.getIdentityHexString(bd);
return resolveInnerBean(argName, innerBeanName, bd);
}
else if (value
instanceof ManagedArray) {
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) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(),
this.beanName,
"Error resolving array type for " + argName, ex);
}
}
else {
elementType = Object.class;
}
}
return resolveManagedArray(argName, (List<?>) value, elementType);
}
else if (value
instanceof ManagedList) {
return resolveManagedList(argName, (List<?>) value);
}
else if (value
instanceof ManagedSet) {
return resolveManagedSet(argName, (Set<?>) value);
}
else if (value
instanceof ManagedMap) {
return resolveManagedMap(argName, (Map<?, ?>) value);
}
else if (value
instanceof ManagedProperties) {
Properties original = (Properties) value;
Properties copy =
new Properties();
for (Map.Entry<Object, Object> propEntry : original.entrySet()) {
Object propKey = propEntry.getKey();
Object propValue = propEntry.getValue();
if (propKey
instanceof TypedStringValue) {
propKey = evaluate((TypedStringValue) propKey);
}
if (propValue
instanceof TypedStringValue) {
propValue = evaluate((TypedStringValue) propValue);
}
copy.put(propKey, propValue);
}
return copy;
}
else if (value
instanceof TypedStringValue) {
TypedStringValue typedStringValue = (TypedStringValue) value;
Object valueObject = evaluate(typedStringValue);
try {
Class<?> resolvedTargetType = resolveTargetType(typedStringValue);
if (resolvedTargetType !=
null) {
return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType);
}
else {
return valueObject;
}
}
catch (Throwable ex) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(),
this.beanName,
"Error converting typed String value for " + argName, ex);
}
}
else {
return evaluate(value);
}
}
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
在配置Bean的属性的时候,属性可能有多种类型,我们再进行注入的时候,不同的属性类型我们不可能一概而论的进行处理,集合类型的属性和非集合类型具备很大的差别,对不同的类型应该有不同的解析处理过程,故该方法流程中首先判断value的类型然后在分别调用 resolveManagedList()、 resolveManagedList() 、 resolveManagedList()等方法进行具体的解析。为了掌握大体的主线,这里我们就不详细展示这几个方法源码,感兴趣的可以自己下来分析。
在完成这个解析过程后,已经为依赖注入准备好了条件,下面的 setPropertyValue() 方法是真正设置属性依赖的地方,该方法的实现是在BeanWrapper的实现类BeanWrapperImpl中,其代码如下:
setPropertyValue方法
protected void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv)
throws BeansException {
String propertyName = tokens.canonicalName;
String actualName = tokens.actualName;
if (tokens.keys !=
null) {
PropertyTokenHolder getterTokens =
new PropertyTokenHolder();
getterTokens.canonicalName = tokens.canonicalName;
getterTokens.actualName = tokens.actualName;
getterTokens.keys =
new String[tokens.keys.length -
1];
System.arraycopy(tokens.keys,
0, getterTokens.keys,
0, tokens.keys.length -
1);
Object propValue;
try {
propValue = getPropertyValue(getterTokens);
}
catch (NotReadablePropertyException ex) {
throw new NotWritablePropertyException(getRootClass(),
this.nestedPath + propertyName,
"Cannot access indexed value in property referenced " +
"in indexed property path '" + propertyName +
"'", ex);
}
String key = tokens.keys[tokens.keys.length -
1];
if (propValue ==
null) {
if (isAutoGrowNestedPaths()) {
int lastKeyIndex = tokens.canonicalName.lastIndexOf(
'[');
getterTokens.canonicalName = tokens.canonicalName.substring(
0, lastKeyIndex);
propValue = setDefaultValue(getterTokens);
}
else {
throw new NullValueInNestedPathException(getRootClass(),
this.nestedPath + propertyName,
"Cannot access indexed value in property referenced " +
"in indexed property path '" + propertyName +
"': returned null");
}
}
if (propValue.getClass().isArray()) {
PropertyHandler ph = getLocalPropertyHandler(actualName);
Class<?> requiredType = propValue.getClass().getComponentType();
int arrayIndex = Integer.parseInt(key);
Object oldValue =
null;
try {
if (isExtractOldValueForEditor() && arrayIndex < Array.getLength(propValue)) {
oldValue = Array.get(propValue, arrayIndex);
}
Object convertedValue = convertIfNecessary(propertyName, 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(actualName, newArray);
propValue = getPropertyValue(actualName);
}
Array.set(propValue, arrayIndex, convertedValue);
}
catch (IndexOutOfBoundsException ex) {
throw new InvalidPropertyException(getRootClass(),
this.nestedPath + propertyName,
"Invalid array index in property path '" + propertyName +
"'", ex);
}
}
else if (propValue
instanceof List) {
PropertyHandler ph = getPropertyHandler(actualName);
Class<?> requiredType = ph.getCollectionType(tokens.keys.length);
List<Object> list = (List<Object>) propValue;
int index = Integer.parseInt(key);
Object oldValue =
null;
if (isExtractOldValueForEditor() && index < list.size()) {
oldValue = list.get(index);
}
Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(),
requiredType, ph.nested(tokens.keys.length));
int size = list.size();
if (index >= size && index <
this.autoGrowCollectionLimit) {
for (
int i = size; i < index; i++) {
try {
list.add(
null);
}
catch (NullPointerException ex) {
throw new InvalidPropertyException(getRootClass(),
this.nestedPath + propertyName,
"Cannot set element with index " + index +
" in List of size " +
size +
", accessed using property path '" + propertyName +
"': List does not support filling up gaps with null elements");
}
}
list.add(convertedValue);
}
else {
try {
list.set(index, convertedValue);
}
catch (IndexOutOfBoundsException ex) {
throw new InvalidPropertyException(getRootClass(),
this.nestedPath + propertyName,
"Invalid list index in property path '" + propertyName +
"'", ex);
}
}
}
else if (propValue
instanceof Map) {
PropertyHandler ph = getLocalPropertyHandler(actualName);
Class<?> mapKeyType = ph.getMapKeyType(tokens.keys.length);
Class<?> mapValueType = ph.getMapValueType(tokens.keys.length);
Map<Object, Object> map = (Map<Object, Object>) propValue;
TypeDescriptor typeDescriptor = TypeDescriptor.valueOf(mapKeyType);
Object convertedMapKey = convertIfNecessary(
null,
null, key, mapKeyType, typeDescriptor);
Object oldValue =
null;
if (isExtractOldValueForEditor()) {
oldValue = map.get(convertedMapKey);
}
Object convertedMapValue = convertIfNecessary(propertyName, oldValue, pv.getValue(),
mapValueType, ph.nested(tokens.keys.length));
map.put(convertedMapKey, convertedMapValue);
}
else {
throw new InvalidPropertyException(getRootClass(),
this.nestedPath + propertyName,
"Property referenced in indexed property path '" + propertyName +
"' is neither an array nor a List nor a Map; returned value was [" + propValue +
"]");
}
}
else {
PropertyHandler ph = getLocalPropertyHandler(actualName);
if (ph ==
null || !ph.isWritable()) {
if (pv.isOptional()) {
if (logger.isDebugEnabled()) {
logger.debug(
"Ignoring optional value for property '" + actualName +
"' - property not found on bean class [" + getRootClass().getName() +
"]");
}
return;
}
else {
throw createNotWritablePropertyException(propertyName);
}
}
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()) {
try {
oldValue = ph.getValue();
}
catch (Exception ex) {
if (ex
instanceof PrivilegedActionException) {
ex = ((PrivilegedActionException) ex).getException();
}
if (logger.isDebugEnabled()) {
logger.debug(
"Could not read previous value of property '" +
this.nestedPath + propertyName +
"'", ex);
}
}
}
valueToApply = convertForProperty(
propertyName, oldValue, originalValue, ph.toTypeDescriptor());
}
pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);
}
ph.setValue(
this.wrappedObject, valueToApply);
}
catch (TypeMismatchException ex) {
throw ex;
}
catch (InvocationTargetException ex) {
PropertyChangeEvent propertyChangeEvent =
new PropertyChangeEvent(
this.rootObject,
this.nestedPath + propertyName, oldValue, pv.getValue());
if (ex.getTargetException()
instanceof ClassCastException) {
throw new TypeMismatchException(propertyChangeEvent, ph.getPropertyType(), ex.getTargetException());
}
else {
Throwable cause = ex.getTargetException();
if (cause
instanceof UndeclaredThrowableException) {
cause = cause.getCause();
}
throw new MethodInvocationException(propertyChangeEvent, cause);
}
}
catch (Exception ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(
this.rootObject,
this.nestedPath + propertyName, oldValue, pv.getValue());
throw new MethodInvocationException(pce, ex);
}
}
}
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
到了这里,就完成了对Bean各种属性的依赖注入的过程,整个过程我们只要把握住 getBean 这个依赖注入的入口,一步步分析下去,就可以完成对整个依赖注入的把握。