2.4 IoC容器的依赖注入
上面对IoC容器的初始化过程进行了详细的分析,这个初始化过程完成的主要工作是在IoC容器中建立BeanDefinition数据映射。在此过程中并没有看到IoC容器对Bean依赖关系进行注入,接下来分析一下IoC容器是怎样对Bean的依赖关系进行注入的。
假设当前IoC容器已经载入了用户定义的Bean信息,开始分析依赖注入的原理。首先,注意到依赖注入的过程是用户第一次向IoC容器索要Bean时触发的,当然也有例外,也就是我们可以在BeanDefinition信息中通过控制lazy-init属性来让容器完成对Bean的预实例化。这个预实例化实际上也是一个完成依赖注入的过程,但它是在初始化的过程中完成的,稍后我们会详细分析这个预实例化的处理。当用户向IoC容器索要Bean时,如果读者还有印象,那么一定还记得在基本的IoC容器接口BeanFactory中,有一个getBean的接口定义,这个接口的实现就是触发依赖注入发生的地方。为了进一步了解这个依赖注入过程的实现,下面从DefaultListableBeanFactory的基类AbstractBeanFactory入手去看看getBean的实现,如代码清单2-22所示。
代码清单2-22 getBean触发的依赖注入
//--------------------------------------------------------------------
// 这里是对 BeanFactory接口的实现,比如getBean接口方法
// 这些getBean接口方法最终是通过调用doGetBean来实现的
//--------------------------------------------------------------------
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}
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);
}
//这里是实际取得Bean的地方,也是触发依赖注入发生的地方
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;
//先从缓存中取得Bean,处理那些已经被创建过的单件模式的Bean,对这种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 + "'");
}
}
/*这里的getObjectForBeanInstance完成的是FactoryBean的相关处理,以取得FactoryBean的生产结果, BeanFactory和FactoryBean的区别已经在前面讲过,这个过程在后面还会详细地分析*/
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
/*这里对IoC容器中的BeanDefintion是否存在进行检查,检查是否能在当前的BeanFactory中取得需要的Bean。如果在当前的工厂中取不到,则到双亲BeanFactory中去取;如果当前的双亲工厂取不到,那就顺着双亲BeanFactory链一直向上查找*/
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);
}
//这里根据Bean的名字取得BeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
//获取当前Bean的所有依赖Bean,这样会触发getBean的递归调用,直到取到一个没有
//任何依赖的Bean为止
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
getBean(dependsOnBean);
registerDependentBean(dependsOnBean, beanName);
}
}
/*这里通过调用createBean方法创建Singleton bean的实例,这里有一个回调函数getObject,会在getSingleton中调用ObjectFactory的createBean*/
//下面会进入到createBean中进行详细分析
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//这里是创建prototype bean的地方
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 '"
+ scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory() {
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);
}
}
}
// 这里对创建的Bean进行类型检查,如果没有问题,就返回这个新创建的Bean,这个Bean已经
//是包含了依赖关系的Bean
if (requiredType != null && bean != null && !requiredType.
isAssignableFrom(bean.getClass())) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return (T) bean;
}
这个就是依赖注入的入口,在这里触发了依赖注入,而依赖注入的发生是在容器中的BeanDefinition数据已经建立好的前提下进行的。“程序=数据+算法,”很经典的一句话,前面的BeanDefinition就是数据,下面看看这些数据是怎样为依赖注入服务的。虽然依赖注入的过程不涉及复杂的算法问题,但这个过程也不简单,因为我们都知道,对于IoC容器的使用,Spring提供了许多的参数配置,每一个参数配置实际上代表了一个IoC容器的实现特性,这些特性的实现很多都需要在依赖注入的过程中或者对Bean进行生命周期管理的过程中完成。尽管可以用最简单的方式来描述IoC容器,将它视为一个hashMap,但只能说这个hashMap是容器的最基本的数据结构,而不是IoC容器的全部。Spring IoC容器作为一个产品,其价值体现在一系列相关的产品特性上,这些产品特性以依赖反转模式的实现为核心,为用户更好地使用依赖反转提供便利,从而实现了一个完整的IoC容器产品。这些产品特性的实现并不是一个简单的过程,它提供了一个成熟的IoC容器产品供用户使用。所以,尽管Spring IoC容器没有什么独特的算法,但却可以看成是一个成功的软件工程产品,有许多值得我们学习的地方。
关于这个依赖注入的详细过程会在下面进行分析
重点来说,getBean是依赖注入的起点,之后会调用createBean,下面通过createBean代码来了解这个实现过程。在这个过程中,Bean对象会依据BeanDefinition定义的要求生成。在AbstractAutowireCapableBeanFactory中实现了这个createBean,createBean不但生成了需要的Bean,还对Bean初始化进行了处理,比如实现了在BeanDefinition中的init-method属性定义,Bean后置处理器等。具体的过程如代码清单2-23所示。
代码清单2-23 AbstractAutowireCapableBeanFactory中的createBean
protected Object createBean(final String beanName, final RootBeanDefinition
mbd, final Object[] args)
throws BeanCreationException {
AccessControlContext acc = AccessController.getContext();
return AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
// 这里判断需要创建的Bean是否可以实例化,这个类是否可以通过类装载器来载入
resolveBeanClass(mbd, beanName);
try {
mbd.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// 如果Bean配置了PostProcessor,那么这里返回的是一个proxy
Object bean = resolveBeforeInstantiation(beanName, mbd);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
//这里是创建Bean的调用
Object beanInstance = doCreateBean(beanName, mbd, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
}, acc);
}
//接着到doCreateBean中去看看Bean是怎样生成的
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd,
final Object[] args) {
// 这个BeanWrapper是用来持有创建出来的Bean对象的
BeanWrapper instanceWrapper = null;
//如果是Singleton,先把缓存中的同名Bean清除
if(mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
//这里是创建Bean的地方,由createBeanInstance来完成
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() {
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
//这里是对Bean的初始化,依赖注入往往在这里发生,这个exposedObject在初始化处理完以后会
//返回作为依赖注入完成后的Bean
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
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;
}
在这里我们看到,与依赖注入关系特别密切的方法有createBeanInstance和populateBean,下面分别介绍这两个方法。在createBeanInstance中生成了Bean所包含的Java对象,这个对象的生成有很多种不同的方式,可以通过工厂方法生成,也可以通过容器的autowire特性生成,这些生成方式都是由相关的BeanDefinition来指定的。如代码清单2-24所示,可以看到不同生成方式对应的实现。
代码清单2-24 Bean包含的Java对象的生成
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition
mbd, Object[] args) {
// 确认需要创建的Bean实例的类可以实例化
Class beanClass = resolveBeanClass(mbd, beanName);
//这里使用工厂方法对Bean进行实例化
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
if (mbd.resolvedConstructorOrFactoryMethod != null) {
if (mbd.constructorArgumentsResolved) {
return autowireConstructor(beanName, mbd, null, args);
}
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);
}
// 使用默认的构造函数对Bean进行实例化
return instantiateBean(beanName, mbd);
}
//最常见的实例化过程instantiateBean
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
//使用默认的实例化策略对Bean进行实例化,默认的实例化策略是
//CglibSubclassingInstantiationStrategy,也就是使用CGLIB来对Bean进行实例化
//接着再看CglibSubclassingInstantiationStrategy的实现
try {
Object beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Instantiation of bean failed", ex);
}
}
这里用cglib对Bean进行实例化。cglib是一个常用的字节码生成器的类库,它提供了一系列的API来提供生成和转换Java的字节码的功能。在Spring AOP中也使用cglib对Java的字节码进行增强。在IoC容器中,要了解怎样使用cglib来生成Bean对象,需要看一下SimpleInstantiationStrategy类。这个Strategy是Spring用来生成Bean对象的默认类,它提供了两种实例化Java对象的方法,一种是通过BeanUtils,它使用了JVM的反射功能,一种是通过前面提到的cglib来生成,如代码清单2-25所示。
代码清单2-25 使用SimpleInstantiationStrategy生成Java对象
public class SimpleInstantiationStrategy implements InstantiationStrategy {
public Object instantiate(
RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {
if (beanDefinition.getMethodOverrides().isEmpty()) {
//这里取得指定的构造器或者生成对象的工厂方法来对Bean进行实例化
Constructor constructorToUse = (Constructor) beanDefinition.
resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
Class clazz = beanDefinition.getBeanClass();
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class
is an interface");
}
try {
constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Exception ex) {
throw new BeanInstantiationException(clazz, "No default
constructor found", ex);
}
}
//通过BeanUtils进行实例化,这个BeanUtils的实例化通过Constructor来实例化Bean,
//在BeanUtils中可以看到具体的调用ctor.newInstance(args)
return BeanUtils.instantiateClass(constructorToUse, null);
}
else {
//使用CGLIB来实例化对象
return instantiateWithMethodInjection(beanDefinition, beanName, owner);
}
}
在cglibSubclassingInstantiationStrategy中可以看到具体的实例化过程和cglib的使用方法,这里就不对cglib的使用进行过多阐述了。如果读者有兴趣,可以去阅读cglib的使用文档,不过这里的Spring代码可以为使用cglib提供很好的参考。这里的Enhancer类,已经是cglib的类了,通过这个Enhancer生成Java对象,使用的是Enhancer的create方法,如代码清单2-26所示。
代码清单2-26 使用CGLIB的Enhancer生成Java对象
public Object instantiate(Constructor ctor, Object[] args) {
//生成Enhancer对象,并为Enhancer对象设置生成Java对象的参数,比如基类、回调方法等
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.beanDefinition.getBeanClass());
enhancer.setCallbackFilter(new CallbackFilterImpl());
enhancer.setCallbacks(new Callback[] {
NoOp.INSTANCE,
new LookupOverrideMethodInterceptor(),
new ReplaceOverrideMethodInterceptor()
});
//使用cglib的create生成实例化的Bean对象
return (ctor == null) ?
enhancer.create() :
enhancer.create(ctor.getParameterTypes(), args);
}
到这里已经分析了实例化Bean对象的整个过程。在实例化Bean对象生成的基础上,再介绍一下Spring是怎样对这些对象进行处理的,也就是Bean对象生成以后,怎样把这些Bean对象的依赖关系设置好,完成整个依赖注入过程。这个过程涉及对各种Bean对象的属性的处理过程(即依赖关系处理的过程),这些依赖关系处理的依据就是已经解析得到的BeanDefinition。要详细了解这个过程,需要回到前面的populateBean方法,这个方法在AbstractAutowireCapableBeanFactory中的实现如代码清单2-27所示。
代码清单2-27 populateBean的实现
protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) {
//这里取得在BeanDefinition中设置的property值,这些property来自对BeanDefinition的解析
//具体的解析过程可以参看对载入和解析BeanDefinition的分析
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;
}
//开始进行依赖注入过程,先处理autowire的注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 这里是对autowire注入的处理,可以根据Bean的名字或者类型,
//来完成Bean的autowire
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
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);
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBean
PostProcessor) 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);
}
//通过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 (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对BeanDefinition的解析是在
//这个valueResolver中完成的
BeanDefinitionValueResolver valueResolver = new
BeanDefinitionValueResolver(this, beanName, mbd, converter);
//这里为解析值创建一个副本,副本的数据将会被注入到Bean中
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 (originalValue instanceof TypedStringValue && convertible &&
!(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();
}
// 这里是依赖注入发生的地方,会在BeanWrapperImpl中完成
try {
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting
property values", ex);
}
}
这里通过使用BeanDefinitionResolver来对BeanDefinition进行解析,然后注入到property中。下面到BeanDefinitionValueResolver中去看一下解析过程的实现,以对Bean reference进行解析为例,如图2-15所示,可以看到整个Resolve的过程。具体的对Bean reference进行解析的过程如代码清单2-28所示。
图2-15 Resolve的调用过程
代码清单2-28 对Bean Reference的解析
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
try {
//从RuntimeBeanReference取得reference的名字,这个RuntimeBeanReference是在
//载入BeanDefinition时根据配置生成的
String refName = ref.getBeanName();
refName = String.valueOf(evaluate(refName));
//如果ref是在双亲IoC容器中,那就到双亲IoC容器中去获取
if (ref.isToParent()) {
if (this.beanFactory.getParentBeanFactory() == null) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Can't resolve reference to bean '" + refName +
"' in parent factory: no parent factory available");
}
return this.beanFactory.getParentBeanFactory().getBean(refName);
}
//在当前IoC容器中去获取Bean,这里会触发一个getBean的过程,如果依赖注入没有发生,这里会
//触发相应的依赖注入的发生
else {
Object bean = this.beanFactory.getBean(refName);
this.beanFactory.registerDependentBean(refName, this.beanName);
return bean;
}
}
catch (BeansException ex) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Cannot resolve reference to bean '" + ref.getBeanName() + "' while
setting " + argName, ex);
}
}
//下面看一下对其他类型的属性进行注入的例子,比如array和list
private Object resolveManagedArray(Object argName, List<?> ml, Class elementType) {
Object resolved = Array.newInstance(elementType, ml.size());
for (int i = 0; i < ml.size(); i++) {
Array.set(resolved, i,
resolveValueIfNecessary(
argName + " with key " + BeanWrapper.PROPERTY_KEY_PREFIX + i +
BeanWrapper.PROPERTY_KEY_SUFFIX,
ml.get(i)));
}
return resolved;
}
//对于每一个在List中的元素,都会依次进行解析
private List resolveManagedList(Object argName, List<?> ml) {
List<Object> resolved = new ArrayList<Object>(ml.size());
for (int i = 0; i < ml.size(); i++) {
resolved.add(
resolveValueIfNecessary(
argName + " with key " + BeanWrapper.PROPERTY_KEY_PREFIX + i +
BeanWrapper.PROPERTY_KEY_SUFFIX,
ml.get(i)));
}
return resolved;
}
这两种属性的注入都调用了resolveValueIfNecessary,这个方法包含了所有对注入类型的处理。下面看一下resolveValueIfNecessary的实现,如代码清单2-29所示。
代码清单2-29 resolveValueIfNecessary的实现
public Object resolveValueIfNecessary(Object argName, Object value) {
//这里对RuntimeBeanReference进行解析,RuntimeBeanReference是在
//对BeanDefinition进行解析时生成的数据对象
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(evaluate(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;
return resolveInnerBean(argName, "(inner bean)", bd);
}
//这里对ManageArray进行解析
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);
}
//这里对ManageList进行解析
else if (value instanceof ManagedList) {
return resolveManagedList(argName, (List<?>) value);
}
//这里对ManageSet进行解析
else if (value instanceof ManagedSet) {
return resolveManagedSet(argName, (Set<?>) value);
}
//这里对ManageMap进行解析
else if (value instanceof ManagedMap) {
return resolveManagedMap(argName, (Map<?, ?>) value);
}
//这里对ManageProperties进行解析
else if (value instanceof ManagedProperties) {
Properties original = (Properties) value;
Properties copy = new Properties();
for (Map.Entry propEntry : original.entrySet()) {
Object propKey = propEntry.getKey();
Object propValue = propEntry.getValue();
if (propKey instanceof TypedStringValue) {
propKey = ((TypedStringValue) propKey).getValue();
}
if (propValue instanceof TypedStringValue) {
propValue = ((TypedStringValue) propValue).getValue();
}
copy.put(propKey, propValue);
}
return copy;
}
//这里对TypedStringValue进行解析
else if (value instanceof TypedStringValue) {
TypedStringValue typedStringValue = (TypedStringValue) value;
Object valueObject = evaluate(typedStringValue.getValue());
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);
}
}
//对RuntimeBeanReference类型的注入在resolveReference中
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
try {
//从RuntimeBeanReference取得reference的名字,这个RuntimeBeanReference是在
//载入BeanDefinition时根据配置生成的
String refName = ref.getBeanName();
refName = String.valueOf(evaluate(refName));
//如果ref是在双亲IoC容器中,那就到双亲IoC容器中去获取
if (ref.isToParent()) {
if (this.beanFactory.getParentBeanFactory() == null) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Can't resolve reference to bean '" + refName +
"' in parent factory: no parent factory available");
}
return this.beanFactory.getParentBeanFactory().getBean(refName);
}
//在当前IoC容器中取得Bean,这里会触发一个getBean的过程,如果依赖注入没有发生,这里会
//触发相应的依赖注入的发生
else {
Object bean = this.beanFactory.getBean(refName);
this.beanFactory.registerDependentBean(refName, this.beanName);
return bean;
}
}
catch (BeansException ex) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Cannot resolve reference to bean '" +ref.getBeanName() + "' while
setting " + argName, ex);
}
}
//对manageList的处理过程在resolveManagedList中
private List resolveManagedList(Object argName, List<?> ml) {
List<Object> resolved = new ArrayList<Object>(ml.size());
for (int i = 0; i < ml.size(); i++) {
//通过递归的方式,对List的元素进行解析
resolved.add(
resolveValueIfNecessary(
argName + " with key " + BeanWrapper.PROPERTY_
KEY_PREFIX + i + BeanWrapper.PROPERTY_KEY_SUFFIX,
ml.get(i)));
}
return resolved;
}
在完成这个解析过程后,已经为依赖注入准备好了条件,这是真正把Bean对象设置到它所依赖的另一个Bean的属性中去的地方,其中处理的属性是各种各样的。依赖注入的发生是在BeanWrapper的setPropertyValues中实现的,具体的完成却是在BeanWrapper的子类BeanWrapperImpl中实现的,如代码清单2-30所示。
代码清单2-30 BeanWraper完成Bean的属性值注入
private void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws
BeansException {
String propertyName = tokens.canonicalName;
String actualName = tokens.actualName;
if (tokens.keys != null) {
// 设置tokens的索引和keys
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;
//getPropertyValue取得Bean中对注入对象的引用,比如Array、List、Map、Set等
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) {
throw new NullValueInNestedPathException(getRootClass(), this.
nestedPath + propertyName,
"Cannot access indexed value in property referenced " +
"in indexed property path '" + propertyName + "': returned null");
} //这里对Array进行注入
else if (propValue.getClass().isArray()) {
Class requiredType = propValue.getClass().getComponentType();
int arrayIndex = Integer.parseInt(key);
Object oldValue = null;
try {
if (isExtractOldValueForEditor()) {
oldValue = Array.get(propValue, arrayIndex);
}
Object convertedValue = this.typeConverterDelegate.
convertIfNecessary(
propertyName, oldValue, pv.getValue(), requiredType);
Array.set(propValue, Integer.parseInt(key), convertedValue);
}
catch (IllegalArgumentException ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(this.rootObject, this.nestedPath +
propertyName,oldValue, pv.getValue());
throw new TypeMismatchException(pce, requiredType, ex);
}
catch (IllegalStateException ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(this.rootObject, this.nestedPath +
propertyName, oldValue, pv.getValue());
throw new ConversionNotSupportedException(pce, requiredType, ex);
}
catch (IndexOutOfBoundsException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath +
propertyName,
"Invalid array index in property path '" + propertyName + "'", ex);
}
} //这里对List进行注入
else if (propValue instanceof List) {
PropertyDescriptor pd = getCachedIntrospectionResults().
getPropertyDescriptor(actualName);
Class requiredType = GenericCollectionTypeResolver.getCollectionReturnType(
pd.getReadMethod(), tokens.keys.length);
List list = (List) propValue;
int index = Integer.parseInt(key);
Object oldValue = null;
if (isExtractOldValueForEditor() && index < list.size()) {
oldValue = list.get(index);
}
try {
Object convertedValue = this.typeConverterDelegate.
convertIfNecessary(
propertyName, oldValue, pv.getValue(), requiredType);
if (index < list.size()) {
list.set(index, convertedValue);
}
else if (index >= list.size()) {
for (int i = list.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 " +
list.size() + ", accessed using property path '"
+ propertyName +
"': List does not support filling up gaps with
null elements");
}
}
list.add(convertedValue);
}
}
catch (IllegalArgumentException ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(this.rootObject, this.nestedPath
+ propertyName, oldValue, pv.getValue());
throw new TypeMismatchException(pce, requiredType, ex);
}
} //这里对Map进行注入
else if (propValue instanceof Map) {
PropertyDescriptor pd = getCachedIntrospectionResults().
getPropertyDescriptor(actualName);
Class mapKeyType = GenericCollectionTypeResolver.
getMapKeyReturnType(
pd.getReadMethod(), tokens.keys.length);
Class mapValueType = GenericCollectionTypeResolver.
getMapValueReturnType(
pd.getReadMethod(), tokens.keys.length);
Map map = (Map) propValue;
Object convertedMapKey;
Object convertedMapValue;
try {
convertedMapKey = this.typeConverterDelegate.
convertIfNecessary(key, mapKeyType);
}
catch (IllegalArgumentException ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(this.rootObject, this.nestedPath +
propertyName, null, pv.getValue());
throw new TypeMismatchException(pce, mapKeyType, ex);
}
Object oldValue = null;
if (isExtractOldValueForEditor()) {
oldValue = map.get(convertedMapKey);
}
try {
convertedMapValue = this.typeConverterDelegate.convertIfNecessary(
propertyName, oldValue, pv.getValue(), mapValueType, null,
new MethodParameter(pd.getReadMethod(), -1, tokens.keys.length + 1));
}
catch (IllegalArgumentException ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(this.rootObject, this.nestedPath +
propertyName, oldValue, pv.getValue());
throw new TypeMismatchException(pce, mapValueType, ex);
}
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 [" +
pv.getValue() + "]");
}
}//这里对非集合类的域进行注入
else {
PropertyDescriptor pd = pv.resolvedDescriptor;
if (pd == null || !pd.getWriteMethod().getDeclaringClass().
isInstance(this.object)) {
pd = getCachedIntrospectionResults().
getPropertyDescriptor(actualName);
if (pd == null || pd.getWriteMethod() == null) {
PropertyMatches matches = PropertyMatches.forProperty
(propertyName, getRootClass());
throw new NotWritablePropertyException(
getRootClass(), this.nestedPath + propertyName,
matches.buildErrorMessage(), matches.getPossibleMatches());
}
pv.getOriginalPropertyValue().resolvedDescriptor = pd;
}
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() && pd.getReadMethod() != null) {
Method readMethod = pd.getReadMethod();
if (!Modifier.isPublic(readMethod.
getDeclaringClass().getModifiers())) {
readMethod.setAccessible(true);
}
try {
oldValue = readMethod.invoke(this.object);
}
catch (Exception ex) {
if (logger.isDebugEnabled()) {
logger.debug("Could not read previous value of property '" +
this.nestedPath + propertyName + "'", ex);
}
}
}
valueToApply = this.typeConverterDelegate.convertIfNecessary
(oldValue, originalValue, pd);
}
pv.getOriginalPropertyValue().conversionNecessary = (valueToApply !=
originalValue);
}
//这里取得注入属性的set方法,通过反射机制,把对象注入进去
Method writeMethod = pd.getWriteMethod();
if (!Modifier.isPublic(writeMethod.getDeclaringClass().
getModifiers())) {
writeMethod.setAccessible(true);
}
writeMethod.invoke(this.object, valueToApply);
}
catch (InvocationTargetException ex) {
PropertyChangeEvent propertyChangeEvent =
new PropertyChangeEvent(this.rootObject, this.nestedPath +
propertyName, oldValue, pv.getValue());
if (ex.getTargetException() instanceof ClassCastException) {
throw new TypeMismatchException(propertyChange
Event, pd.getPropertyType(),ex.getTargetException());
}
else {
throw new MethodInvocationException(propertyChangeEvent, ex.
getTargetException());
}
}
catch (IllegalArgumentException ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(this.rootObject, this.nestedPath +
propertyName, oldValue, pv.getValue());
throw new TypeMismatchException(pce, pd.getPropertyType(), ex);
}
catch (IllegalStateException ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(this.rootObject, this.nestedPath +
propertyName, oldValue, pv.getValue());
throw new ConversionNotSupportedException(pce, pd.getPropertyType(), ex);
}
catch (IllegalAccessException ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName,
oldValue, pv.getValue());
throw new MethodInvocationException(pce, ex);
}
}
}
这样就完成了对各种Bean属性的依赖注入过程。从代码实现细节上看,对比Spring 2.0的源代码实现,Spring 3.0的源代码已经有了很大的改进,整个过程更为清晰了,特别是关于依赖注入的部分。如果读者有兴趣,可以比较一下Spring 2.0和Spring 3.0关于依赖注入部分的代码实现,这样可以更清晰地看到Spring源代码的演进过程,也可以看到Spring团队对代码进行重构的思路。
在Bean的创建和对象依赖注入的过程中,需要依据BeanDefinition中的信息来递归地完成依赖注入。从上面的几个递归过程中可以看到,这些递归都是以getBean为入口的。一个递归是在上下文体系中查找需要的Bean和创建Bean的递归调用;另一个递归是在依赖注入时,通过递归调用容器的getBean方法,得到当前Bean的依赖Bean,同时也触发对依赖Bean的创建和注入。在对Bean的属性进行依赖注入时,解析的过程也是一个递归的过程。这样,根据依赖关系,一层一层地完成Bean的创建和注入,直到最后完成当前Bean的创建。有了这个顶层Bean的创建和对它的属性依赖注入的完成,意味着和当前Bean相关的整个依赖链的注入也完成了。
在Bean创建和依赖注入完成以后,在IoC容器中建立起一系列依靠依赖关系联系起来的Bean,这个Bean已经不是简单的Java对象了。该Bean系列以及Bean之间的依赖关系建立完成以后,通过IoC容器的相关接口方法,就可以非常方便地供上层应用使用了。继续以水桶为例,到这里,我们不但找到了水源,而且成功地把水装到了水桶中,同时对水桶里的水完成了一系列的处理,比如消毒、煮沸……尽管还是水,但经过一系列的处理以后,这些水已经是开水了,可以直接饮用了。