《Spring技术内幕》——2.4节IoC容器的依赖注入

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容器的相关接口方法,就可以非常方便地供上层应用使用了。继续以水桶为例,到这里,我们不但找到了水源,而且成功地把水装到了水桶中,同时对水桶里的水完成了一系列的处理,比如消毒、煮沸……尽管还是水,但经过一系列的处理以后,这些水已经是开水了,可以直接饮用了。

时间: 2024-07-31 08:03:56

《Spring技术内幕》——2.4节IoC容器的依赖注入的相关文章

《Spring技术内幕》——2.5节容器其他相关特性的设计与实现

2.5 容器其他相关特性的设计与实现 在前面的IoC原理分析中,我们对IoC容器的主要功能进行了分析,比如BeanDefinition的载入和解析,依赖注入的实现,等等.为了更全面地理解IoC容器特性的设计,下面对容器的一些其他相关特性的设计原理也进行简要的分析.这些特性都是在使用IoC容器的时候会经常遇到的.这些特性其实很多,在这里只选择了几个例子供读者参考.在了解了IoC容器的整体运行原理以后,对这些特性的分析已经不再是一件困难的事情.如果读者对其他IoC容器的特性感兴趣,也可以按照同样的思

《Spring技术内幕》——导读

目 录 前言 第1章 Spring的设计理念和整体架构1.1 Spring的各个子项目 1.2 Spring的设计目标 1.3 Spring的整体架构 1.4 Spring的应用场景 1.5 小结 第一部分 Spring核心实现篇 第2章 Spring Framework的核心:IoC容器的实现 2.1 Spring IoC容器概述2.2 IoC容器系列的设计与实现:BeanFactory和ApplicationContext 2.3 IC容器的初始化过程 2.4 IoC容器的依赖注入 2.5

《Spring技术内幕》——2.2节IoC容器系列的设计与实现:BeanFactory和ApplicationContext

2.2 IoC容器系列的设计与实现:BeanFactory和ApplicationContext在Spring IoC容器的设计中,我们可以看到两个主要的容器系列,一个是实现BeanFactory接口的简单容器系列,这系列容器只实现了容器的最基本功能:另一个是ApplicationContext应用上下文,它作为容器的高级形态而存在.应用上下文在简单容器的基础上,增加了许多面向框架的特性,同时对应用环境作了许多适配.有了这两种基本的容器系列,基本上可以满足用户对IoC容器使用的大部分需求了.下面

《Spring技术内幕》——1.4节Spring的应用场景

1.4 Spring的应用场景 通过介绍Spring架构设计,我们了解到Spring是一个轻量级的框架.在Spring这个一站式的应用平台或框架中,其中的各个模块除了依赖IoC容器和AOP之外,相互之间并没有很强的耦合性.Spring的最终目标是简化应用开发的编程模型.它所提供的服务,可以贯穿应用到整个软件中,从最上层的Web UI到底层的数据操作,到其他企业信息数据的集成,再到各种J2EE服务的使用,等等.这些企业应用服务,Spring都通过其特有的IoC容器和AOP模块实现.在实现过程中,S

Spring源代码解析(一):IOC容器

在认真学习Rod.Johnson的三部曲之一:< >,顺便也看了看源代码想知道个究竟,抛砖引玉,有兴趣的同志一起讨论研究吧! 以下内容引自博客:http://jiwenke-spring.blogspot.com/,欢迎指导:) 在Spring中,IOC容器的重要地位我们就不多说了,对于Spring的使用者而言,IOC容器实际上是什么呢?我们可以说BeanFactory就是我们看到的IoC容器,当然了Spring为我们准备了许多种IoC容器来使用,这样可以方便我们从不同的层面,不同的资源位置,

《Spring技术内幕》——2.3节IoC容器的初始化过程

2.3 IoC容器的初始化过程 简单来说,IoC容器的初始化是由前面介绍的refresh()方法来启动的,这个方法标志着IoC容器的正式启动.具体来说,这个启动包括BeanDefinition的Resouce定位.载入和注册三个基本过程.如果我们了解如何编程式地使用IoC容器,就可以清楚地看到Resource定位和载入过程的接口调用.在下面的内容里,我们将会详细分析这三个过程的实现. 在分析之前,要提醒读者注意的是,Spring把这三个过程分开,并使用不同的模块来完成,如使用相应的Resourc

《Spring技术内幕》——1.1节Spring的各个子项目

第1章 Spring的设计理念和整体架构 横看成岭侧成峰,远近高低各不同. 不识庐山真面目,只缘身在此山中. -[宋]苏轼<题西林壁> 本章内容 Spring的各个子项目 Spring的设计目标 Spring的整体架构 Spring的应用场景 1.1 Spring的各个子项目 打开Spring社区网站http://www.springsource.org, 我们可以看到围绕Spring核心构建出的一个丰富的平台生态系统.在这个平台生态系统中,除了Spring本身,还有许多值得注意的子项目.对S

《Spring技术内幕》——1.2节Spring的设计目标

1.2 Spring的设计目标 如果我们要简要地描述Spring的设计目标,可以这么说,Spring为开发者提供的是一个一站式的轻量级应用开发框架(平台).作为平台,Spring抽象了我们在许多应用开发中遇到的共性问题:同时,作为一个轻量级的应用开发框架,Spring和传统的J2EE开发相比,有其自身的特点.通过这些自身的特点, Spring充分体现了它的设计理念:在Java EE的应用开发中,支持POJO和使用JavaBean的开发方式,使应用面向接口开发,充分支持OO(面向对象)的设计方法.

《Spring技术内幕》——1.3节Spring的整体架构

1.3 Spring的整体架构 了解了Spring的设计理念之后,我们继续介绍Spring的整体架构.在Spring中,我们大致按照一个参考关系,将其划分为几个层次,比如IoC容器.AOP核心模块.封装的Java EE服务.作为中间的驱动组件.其他作为上层的应用,这些应用不但包括来源于社区的应用封装,如ACEGI,也包括使用Spring作为平台开发出来的各种类型的企业应用. 从技术上看,Spring是封装得很清晰的一个分层架构,可以参考如图1-4所示的Spring架构图. 在这个架构图中,我们可