Spring源码解析之IoC容器
大家好,几年前笔者写过一篇关于Spring的IoC容器相关文章,出门左转还可以找到它。工作几年,几乎每天都离不开Spring的框架,从最开始的SSH到现在的SSM,从以前的XML配置文件到现在的注解,Spring的使用也越来越方便,但同时也会让我们忘了它优雅的背后是许多前辈和同行的努力。也不算立个Flag,准备有时间就写写Spring源码的解析,可能会涉及架构,设计模式等,写到哪里算哪里,如果写的多了再开个专栏,优化一下。
- BeanFactory容器设计原理
- ApplicationContext容器设计原理
- BeanDefinition资源定位
- BeanDefinition加载解析
- BeanDefinition注册
- IoC容器的依赖注入
Spring的IoC
应该说,Spring的IoC是整个框架基础的基础,IoC(控制反转)解决最根本的问题是组件之间的高耦合,组件间高耦合的坏处和低耦合的好处就不啰嗦了,这里要稍微讲下,IoC和依赖注入并不是完全相等的,IoC其实是包括依赖注入(DI)和依赖查找(DL).Spring的IoC更多的是使用依赖注入(依赖注入分为:接口注入、setter注入、构造函数注入;Spring的IoC中,setter注入是常见方式,其次是构造函数注入),因为它更准确的描述了IoC的设计理念,将组件之间的依赖关系由Spring的IoC容器在应用系统运行期来决定,由容器动态地将某种依赖关系的目标对象实例注入到应用系统中的各个关联的组件之中。依赖查找是容器中的受控对象通过容器的API(例如getBean())来查找自己所依赖的资源和协作对象。这种方式虽然降低了对象间的依赖,但是同时也使用到了容器的API,造成了我们无法在容器外使用和测试对象。
Spring的使用现在更多是使用注解的方式,但本文还是会用之前更常用的XML配置的方式作为解析的入口。
BeanFactory容器设计原理
作为容器,先必须提到bean,它是Spring中最核心的概念了,是Spring容器所承载的单位载体。一个bean在配置文件中声明方式简单的形如:
<bean id="testBean" class="org.bayes.model.TestBean"/>
是的,相信对Spring有一定使用经验的你已经知道了,这样简单的配置就可以在Spring启动时对TestBean.class进行实例化了。问题是,Spring是如何做到的?不妨我们大胆设想一下,完成Bean实例化的过程:
- 加载并读取XML配置文件。
- 解析配置文件中的bean标签及其内容。
- 实例化对应的class。
当然,这3个步骤是非常简单,Spring的实现在步骤上差不多,后面会讲到;但Spring在实现这几个步骤的功能时是非常复杂的,先上个图,大家简单感受一下:
这个是Spring的IoC容器中BeanFactory接口的实现,另一个是ApplicationContext应用上下文作为容器的高级形态存在(后面我们再讲)。BeanFactory提供了最基本的IoC容器功能,以及所应遵循的最基本的服务约束。下面是BeanFactory接口定义:
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
boolean containsBean(String name);
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
String[] getAliases(String name);
}
可以看到,用户在使用容器时,可以使用转义符“&”来得到FactoryBean本身,以区分通过容器获取FactoryBean产生的对象和FactoryBean自身。在Spring框架下,所有Bean都是由BeanFactory(IoC容器)来管理的,但对于FactoryBean来说,它不是一般的Bean,而是一个能“创造”或“修饰”实例对象的工厂Bean。在BeanFactory接口的基础上,我们以XmlBeanFactory的实现为例来简单说明IoC容器关于BeanFactory实现的设计原理。
public class XmlBeanFactory extends DefaultListableBeanFactory {
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
}
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}
}
DefaultListableBeanFactory和XmlBeanDefinitionReader两个核心类已经出现了。其中DefaultListableBeanFactory是bean加载的核心,它是Spring注册及加载Bean的默认实现。XmlBeanDefinitionReader是对XML配置文件的读取、解析及注册的功能实现。还记得上面“大胆设想”Bean实例化过程的3个步骤吗,上面代码中**this.reader.loadBeanDefinitions(resource);**便是资源加载的入口,那我们就从XmlBeanDefinitionReader.loadBeanDefinitions(resource)开始。接下来,XmlBeanDefinitionReader做了2件事来为BeanDefinition的加载注册做准备:
- 获取XML文件的验证模式(DTD / XSD)。
- 加载XML文件,并得到相应的Document。
注册BeanDefinition是在XmlBeanDefinitionReader中实例化DefaultBeanDefinitionDocumentReader.registerBeanDefinitions方法来完成的。最终使用BeanDefinitionReaderUtils.registerBeanDefinition()方法(BeanDefinitionRegistry接口)实现注册的是DefaultListableBeanFactory.registerBeanDefiniton()。至此,XmlBeanFactory的实现就完成了IoC容器的创建,后面就可以直接使用IoC容器了。
其实,这里面的代码还比较绕,经常是进到代码块里面后就找不到自己的位置了。对照上面的图片(重要步骤由红色字体标注,核心方法名称已在类名下写了出来),读者朋友可以找源码仔细看看,相信对理解整个BeanFactory接口架构有更好的帮助。
ApplicationContext容器设计原理
相比简单的BeanFactory基本IoC容器,我们经常使用应该是ApplicationContext应用上下文的高级形态IoC容器。下面主要以FileSystemXmlApplicationContext的实现为例说明,附以XmlWebApplicationContext和ClassPathXmlApplicationContext。还是延续惯例,先上张图说明一下ApplicationContext接口实现及其与BeanFactory接口的关系:
ApplicationContext的IoC容器初始化是由refresh()方法来启动的。这个启动包括BeanDefinition的Resource定位、载入、注册三个过程。IoC的初始化过程不包括Bean依赖注入的实现,依赖注入一般发生在第一次getBean时(bean的lazyinit属性可改变bean的依赖注入过程)。初始化过程完成后我们再分析一下IoC容器如何对Bean的依赖进行注入的。
首先是Resource定位,即BeanDefinition的资源定位,它由ResourceLoader统一的Resource接口完成,我们使用FileSystemXmlApplicationContext应用上下文,自然会使用FileSystemResouce来进行抽象;如果是ClassPath的Bean定义信息可以使用ClassPathResource,等等。
然后是BeanDefinition的载入,即将用户定义好的Bean表示成IoC容器内部的数据结构BeanDefinition,这里载入也会顺带涉及到解析的过程。
最后是使用BeanDefinitionRegistry接口实现完成向IoC容器注册上面解析的BeanDefinition。
BeanDefinition资源定位
我们从FileSystemXmlApplicationContext具体实现开始:
package org.springframework.context.support;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
public class FileSystemXmlApplicationContext extends AbstractXmlApplicationContext {
...
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
@Override
protected Resource getResourceByPath(String path) {
if (path != null && path.startsWith("/")) {
path = path.substring(1);
}
return new FileSystemResource(path);
}
}
上面提过一下,初始化是从refresh()开始的,但这里我们暂时先重点关注getResourceByPath(path);这个getResourceByPath是在父类AbstractXmlApplicationContext中loadBeanDefinition()方法里调用;XmlBeanDefinitionReader的loadBeanDefinition中被调用的,loadBeanDefinition采用了模板模式,具体的定位实现是由各个子类完成的。这里的XmlBeanDefinitionReader就是在上面BeanFactory容器设计里提到的,同时这个loadBeanDefinition()是使用DefaultListableBeanFactory作为参数传入。至此FileSystemXmlApplicationContext将之前讲到的BeanFactory容器体系的两大核心类都引入进来了。
BeanDefinition的加载解析
引入了DefaultListableBeanFactory和XmlBeanDefinitionReader后就没有什么新鲜的东西了,具体看看加载和解析的代码吧:
package org.springframework.beans.factory.xml;
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
...... //代码太多,省略一部分
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
}
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
......
try {
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
//***************这里是重点*********
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
catch (IOException ex) {
......
}
finally {
......
}
}
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
Document doc = doLoadDocument(inputSource, resource);
return registerBeanDefinitions(doc, resource);
}
catch (BeanDefinitionStoreException ex) {
....
}
}
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
//***************DefaultDocumentLoader来了,资源加载的具体实现********************
return new DefaultDocumentLoader().loadDocument(inputSource, getEntityResolver(), this.errorHandler,
getValidationModeForResource(resource), isNamespaceAware());
}
//**************调用注册的方法,具体实现是在DefaultListableBeanFactory里*************
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
return BeanDefinitionDocumentReader.class.cast(
BeanUtils.instantiateClass(DefaultBeanDefinitionDocumentReader.class)
);
}
}
代码的思路还是比较清晰的,关于解析部分,是在BeanDefinitionParserDelegate类中,读者朋友可以再追踪者看下相关源码。
BeanDefinition注册
上面加载后,就可以将BeanDefinition注册到容器中准备开始使用了。进入到DefaultBeanDefinitionDocumentReader的registerBeanDefinitions()方法里看看,
package org.springframework.beans.factory.xml;
public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
doRegisterBeanDefinitions(root);
}
protected void doRegisterBeanDefinitions(Element root) {
BeanDefinitionParserDelegate parent = this.delegate; //将元素转换为BeanDefinition的实现类
this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isInfoEnabled()) {
logger.info("...");
}
return;
}
}
}
preProcessXml(root); //空方法,留给子类重写
//具体实现在下一段
parseBeanDefinitions(root, this.delegate);
postProcessXml(root); //空方法,留给子类重写
this.delegate = parent;
}
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (Node node : nl){
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate); //具体实现在下一段
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate); //重点快来了,接着往后看
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
/**
* 注册的实现,这里的getReaderContext.getRegistry()即是开始条用时传入的
* XmlBeanDefinitionReader.getRegistry();也就是DefaultListableBeanFactory
* 它是在AbstractXmlApplicationContext里loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
* 时传入定义的
*/
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
}
所谓注册的简单实现就是将 beanName 和对应的 DeanDefinfition放到一个Map里,当然,spring在处理时会稍微复杂一点,后面DefaultListableBeanFactory的代码就不再展示了,有兴趣的同学可以去看看。
万里长征感觉终于快走完了,心中不免小小的激动一下,但是慢着,只是到注册这一步是没有用的,Spring的核心要实现的是依赖注入,那么重点是注入才对啊!原来,我们还没有开始啊…
IoC容器的依赖注入
上面注册完成后,即是在IoC容器中建立了BeanDefinition的数据映射(BeanDefinitionMap),接下来分析IoC容器是如何对Bean的依赖关系进行注入的。首先,依赖注入的过程是第一次向IoC容器获取Bean时触发的。 当用户向IoC容器索要Bean时,在接口BeanFactory中有一个getBean的接口定义,往下从DefaultListableBeanFactory的基类AbstractBeanFactory来看getBean的实现
package org.springframework.beans.factory.support;
...
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
...
public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args) throws BeansException {
return doGetBean(name, requiredType, args, false);
}
@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// 先判断缓存中是否已经有创建好的单例模式的bean.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
...
//这里完成FactoryBean的相关处理,取得FactoryBean的生产结果。
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 顺着双亲BeanFactory链一直向上找
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
...
}
...
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 获取当前bean所有依赖Bean,触发getBean递归调用,直到取到一个没有任何依赖的Bean为止.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
...
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// 调用createBean方法创建Singleton Bean的实例.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// 下面的createBean是创建prototype Bean的.
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);
...
try {
Object scopedInstance = scope.get(beanName, () -> {
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 ...",ex);
}
}
}
...
}
// 对创建的Bean进行类型检查,这个Bean已经是包含了依赖关系的Bean.
if (requiredType != null && !requiredType.isInstance(bean)) {
...
}
return (T) bean;
}
中间省略了很多代码,重点的业务流程和判断,我通过注释提示的方式在上面代码中标注出来了,可以好好看一下,重点就在于这个createBean,它是在子类AbstractAutwireCapableBeanFactory中实现的,虽然代码很多,但还是要贴上来看看:
package org.springframework.beans.factory.support;
...
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
...
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
...
return beanInstance;
}
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) { ///如果是Singleton先把缓存中同名Bean清除
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) { //创建Bean
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
...
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper); //依赖关系的处理过程,后面会再重点讲
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
catch (Throwable ex) {
...
}
...
// Register bean as disposable.
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指定的。下面先看看它的代码,后面再重点看populateBean().
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
// 确认可以实例化.
Class<?> beanClass = resolveBeanClass(mbd, beanName);
...
if (mbd.getFactoryMethodName() != null) { //使用工厂方法对Bean进行实例化
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
...
// 使用构造函数进行实例化
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);
}
//最常用的实例化过程
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() { //CGLib生成Bean,参考SimpleInstantiationStrategy
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) {
...
}
}
以上就是实例化Bean对象的过程了。在Bean对象生成以后,如何把这些Bean对象的依赖关系设置好,如何把Bean对象的属性的依赖关系处理好,就需要依据已经解析好的BeanDefinition信息。详细的过程我们看populateBean()方法:
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues(); //从BeanDefiniton中取得设置的 property值
...
//开始依赖注入的过程,先处理Autowire的注入;可以根据Bean的名字或类型;
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;
}
...
applyPropertyValues(beanName, mbd, bw, pvs); //对属性进行注入
}
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
...
if (System.getSecurityManager() != null) {
if (bw instanceof BeanWrapperImpl) { //注意! 后面依赖注入发生的地方是在这个BeanWrapperImpl中完成的
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
}
}
...
//BeanDefinitionValueResolver对BeanDefinition的解析是在这个valueResolve中完成的
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
// 为解析值创建一个副本,副本数据会被注入到Bean中.
List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size());
...
// 上面提到的,依赖注入发生的地方,在BeanWrapperImpl中完成.
try {
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
这中间还有很多代码及其实现没有讲,但大致的思路上已经完成了对各种Bean属性的依赖注入过程。在Bean的创建和对象依赖注入的过程中,需要依据BeanDefinition中的信息来递归地完成依赖注入。从上面的过程中看,这些递归都是以getBean为入口的。一个递归是在上下文中查找需要的Bean和创建Bean的递归调用;另一个递归是在依赖注入时,通过递归调用容器的getBean方法,得到当前Bean的依赖Bean,同时也触发对依赖Bean的创建和注入。在对Bean的属性进行依赖注入时,解析的过程也是一个递归地过程。根据这些依赖关系,一层层地完成对Bean的创建和注入,直到最后完成当前Bean相关的整个依赖链的注入。
在Bean创建和依赖注入完成后,在IoC容器中建立起来一系列依靠依赖关系联系起来的Bean,此时的这个Bean已经不是一个简单的Java对象的Bean了。
回顾
在对IoC容器的分析中,(参照最上面的第一张图)重点讲了一下BeanFactory和ApplicationContext体系,BeanDefinition的资源定位、加载解析和注册,容器的依赖注入等。通过这些实现过程的分析,我们初步了解了IoC容器的基本工作原理和基本特性的实现思路。但是,Spring IoC容器的内涵特性非常丰富,上面粗陋的分析无法面面俱到,有兴趣的同学可以参照源码继续探索。