我们经常提到spring,就不得不说spring的IOC和AOP。今天我们先说一下spring的IOC。参考书籍:Spring技术内幕
不打算说太多概念性的东西,只是按我看书的理解主要说一下,以后可能有时间会专门在详细的说一下Ioc的实现。
Ioc(Inversion Of Control)控制反转
这里我们到底反转了什么?
这里我们依赖对象的获取被反转了。以前我们都是由两个或多个类通过彼此的合作来实现业务逻辑的,这使得每个对象都需要与其合作的对象(它所依赖的对象)的引用。如果这个获取过程要靠自身实现,那么将导致代码高度耦合并且难以测试。
在面向对象系统中,对象分封装了数据和对数据的处理,对象的依赖关系常常体现在对数据和方法的依赖上。这些依赖关系可以通过把对象的依赖注入交给框架或Ioc容器来完成,这种从具体对象手中交出控制的做法是非常有价值的。
总结:就是以前我们需要控制对象的生成和对象之间依赖的处理,现在这些都交给Ioc容器来控制,我们现在只是需要用这些对象的实现向IOC容器要就行,不需要我们在自己去控制对象的生成和依赖关系的处理。
IOC容器的实现
我们在研究Ioc容器时,可以看到最主要的两个实现,一个是实现BeanFactory接口的简单容器系列,这系列容器只实现了容器的基本功能;另一个是ApplicationContext应用上下文,它作为容器的高级形态而存在。
如果我们把Ioc容器看成是一个水桶,BeanFactory就定义了可以作为水桶的基本功能,比如水桶必须可以装水,要有提手等。而除了基本功能,比如面对不同的厂家,在这个基础上设计了其他各种各样的水桶产品,比如是用塑料做的,还又添加了一个底座等功能。但是不管是什么水桶,都必须有一项基本功能,可以装水。对Spring的具体Ioc容器实现来说,它需要满足BeanFactory这个基本接口的定义,所以在spring的ioc容器实现中,BeanFactory是作为一个最基本的接口类出现的。
在Ioc容器的接口和实现基础上,Spring通过定义BeanDefinition来管理基于spring的应用中的各种对象以及它们之间的相互依赖关系。对Ioc容器来说,BeanDefinition就是对依赖反转模式中管理的对象依赖关系的数据抽象,也是容器实现依赖反转功能的核心数据结构,依赖反转功能都是围绕对这个BeanDefinition的处理来完成的。这些BeanDefinition就像是容器里的水,有了这些基本数据,容器才能够发挥作用。
在Spring代码中,BeanFactory只是一个接口类,并没有给出容器的具体实现。而比如DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext等可以看成容器附加了某种功能的具体实现,也就是具体的容器产品。
其中BeanFactory定义的操作:
public interface BeanFactory {
public static final String FACTORY_BEAN_PREFIX = "&";
public Object getBean(String var1) throws BeansException; //通过名字获取bean
public <T> T getBean(String var1, Class<T> var2) throws BeansException;
public <T> T getBean(Class<T> var1) throws BeansException;
public Object getBean(String var1, Object... var2) throws BeansException;
public boolean containsBean(String var1); //判断容器是否包含指定的bean
public boolean isSingleton(String var1) throws NoSuchBeanDefinitionException; //查询指定名字的bean是不是Singleton类型的bean
public boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;
public boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException; //查询指定了名字的bean的class类型是否是特定的class类型
public Class<?> getType(String var1) throws NoSuchBeanDefinitionException;//查询指定bean的class类型
public String[] getAliases(String var1);//查询指定了名字的bean的所有别名,这些别名都是用户在BeanDefinition中定义的
}
ApplicationContext是在BeanFactory提供的BeanFactory基础上,添加了一些BeanFactory不具备的新特性:
—— 支持不同的信息源。ApplicationContext扩展了MessageSource接口。这些信息源的扩展功能可以支持国际化的实现。
—— 访问资源。 这一特性体现在ResourceLoader和Resource的支持上,这样我们可以从不同地方得到Bean的定义资源。尤其是从不同的I/O途径得到Bean定义信息。ApplicationContext继承了DefaultResourceLoader的子类,因为DefaultResourceLoader是AbstractApplicationContext的基类。
—— 支持应用事件。 继承了接口ApplicationEventPublisher,从而在上下文中引入了事件机制。这些事件和Bean的生命周期的结合为Bean的管理提供了便利。
Ioc容器的初始化过程
Ioc容器的初始化是由refresh()方法来启动的,这个方法标志着Ioc容器的正式启动。这个启动包括BeanDefinition的Resource定位、载入和注册三个基本过程。在Spring中,Spring把这三个过程分开,并使用不同的模块来完成,如使用相应的ResourceLoader、BeanDefinitionReader等模块,使用这样的设计方式,可以让用户更加灵活地对三个过程进行剪裁或扩展。
第一个过程是Resource定位过程。这个Resource定位指的是BeanDefinition的资源定位,它由ResourceLoader通过统一的Resource接口来完成,这个Resource对各种形式的BeanDefinition的使用都提供了统一接口。对于这些BeanDefinition的存在形式,比如,在文件系统中的Bean定义信息可以使用FileSystemResource来进行抽象;在类路径中的Bean定义信息可以使用前面提到的ClassPathResource来使用,等。这个定位过程类似于容器寻找数据的过程,就像用水桶装水先要把水找到一样。
第二个过程是BeanDefinition的载入。这个载入过程是把用户定义好的Bean表示成Ioc容器内部的数据结构,而这个容器内部的数据结构就是BeanDefinition。这个BeanDefinition实际上就是POJO对象在Ioc容器中的抽象,通过这个BeanDefinition定义的数据结构,使Ioc容器能够方便地对POJO对象也就是Bean进行管理。
第三个过程是向Ioc容器注册这些BeanDefinition的过程。这个过程是通过调用BeanDefinitionRegistry接口的实现来完成的。这个注册过程把载入过程中解析得到的BeanDefinition向Ioc容器进行注册。其实是在Ioc容器内部将BeanDefinition注入到一个HashMap中去,Ioc容器就是通过这个HashMap来持有这些BeanDefinition数据的。
这里注意的是:Ioc容器的初始化的过程,在这个过程中,一般不包含Bean依赖注入的实现。在Spring Ioc的设计中,Bean定义的载入和依赖注入是两个独立的过程。依赖注入一般发生在应用第一次通过getBean向容器索取Bean的时候。但有一个例外,在使用Ioc容器时有一个预实例化的配置,通过这个预实例化的配置(具体来说,可以通过为Bean定义信息中的lazyinit属性),用户可以对容器初始化过程做一个微小的控制,从而改变这个被设置了lazyinit属性的Bean的依赖注入的过程。举例来说,如果我们对某个Bean设置了lazyinit属性,那么这个Bean的依赖注入在Ioc容器初始化时就预先完成了,而不需要等到整个初始化完成以后,第一次使用getBean时才会触发。
BeanDifinition的Resource定位
以ApplicationContext为例,因为在ApplicationContext中,spring已经为我们提供了一系列加载不同Resource的读取器的实现,例如FileSystemXmlApplicationContext、ClassPathXmlApplicationContext以及XmlWebApplicationContext等。我们可以从类的名字上面分析,可以知道他们可以提供哪些不同的Resource读入功能,比如FileSystemXmlApplicationContext可以从文件系统载入Resource,ClassPathXmlApplicationContext可以从Class Path载入Resource,XmlWebApplicationContext可以在Web容器中载入Resource等。
我们下面以FileSystemXmlApplicationContext为例,分析这个ApplicationContext的实现。我们可以从源码中看到,这个FileSystemXmlApplicationContext已经通过继承AbstractApplicationContext具备了ResourceLoader读入以Resource定义的BeanDefinition的能力,因为AbstractApplicationContext的基类是DefaultResourceLoader。
而我们现在需要关心的是这个FileSystemXmlApplicationContext在哪里定义了BeanDifinition的读入器BeanDefinitionReader,从而完成BeanDifinition信息的读入呢?我们需要进入FileSystemXmlApplicationContext的基类看一下AbstractRefreshableApplicationContext中看一下。
我们需要重点看它的refershBeanFactory方法的实现,这个refreshBeanFactory被FileSytemXmlApplicationContext构造函数中的refresh调用。在这方法中,通过createBeanFactory构建了一个Ioc容器供ApplicationContext使用,而这个Ioc容器就是DefaultListableBeanFactory(ApplicationContext和XmlBeanFactory也是通过持有或扩展DefaultListableBeanFactory来获取最基本的Ioc容器的功能的)。同时,DefaultListableBeanFactory它启动了loadBeanDefinitions来载入BeanDefinition。从FileSystemXmlApplicationContext中可以看到,在初始化FileSystemXmlApplicationContext的过程中,通过Ioc容器的初始化的refresh来启动整个调用,使用的Ioc容器是DefaultListableBeanFactory。具体的资源载入在XmlBeanDefinitionReader读入BeanDefinition时完成,在XmlBeanDefinitionReader的基类AbstractBeanDefinitionReader中可以看到这个载入过程的具体实现。而载入过程的启动可以在AbstratctRefreshableApplicationContext的loadBeanDefinitions方法中看到。
protected final void refreshBeanFactory() throws BeansException {
// 这里判断,如果已建立了BeanFactory,则销毁并关闭该BeanFactory
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
// 这里是创建并设置持有的DefaultListableBeanFactory的地方同时调用
// loadBeanDefinitions再载入BeanDefinition的信息
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
/*
* 这里就是在上下文创建DefaultListableBeanFactory的地方,而getinternalParentBeanFactory()
* 的具体实现可以参看AbstractApplicationContext中的实现,会根据容器已有的双亲Ioc容器的信息来生成
* DefaultListableBeanFactory的双亲Ioc容器
*/
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
//这里是使用BeanDefinitionReader载入Bean的地方,因为允许有多种载入的方式,
//虽然用的最多的是XML定义的形式,这里通过一个抽象函数把具体的实现委托给子类来完成
protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
throws BeansException, IOException;
//AbstractBeanDefinitionReader中实现的方法
public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
// 这里取得ResourceLoader,使用的是DefaultResourceLoader
ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
}
// 这里对Resource的路径模式进行解析,比如我们设定的各种Ant格式的路劲定义,
// 得到需要的Resource集合,这些Resource集合指向我们已经定义好的BeanDefinition信息,可以是多个文件
if (resourceLoader instanceof ResourcePatternResolver) {
// Resource pattern matching available.
try {
// 调用DefaultResourceLoaderdegetResource完成具体的Resource定位
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
int loadCount = loadBeanDefinitions(resources);
if (actualResources != null) {
for (Resource resource : resources) {
actualResources.add(resource);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
}
return loadCount;
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"Could not resolve bean definition resource pattern [" + location + "]", ex);
}
}
else {
// Can only load single resources by absolute URL.
// 调用DefaultResourceLoader的getResource完成具体的Resource定位
Resource resource = resourceLoader.getResource(location);
int loadCount = loadBeanDefinitions(resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
}
return loadCount;
}
}
//DefaultResourceLoader中的实现
//对于具体的Resource具体过程,我们可以看看DefaultResourceLoader是怎样完成的
public Resource getResource(String location) {
Assert.notNull(location, "Location must not be null");
if (location.startsWith("/")) {
return getResourceByPath(location);
}
// 这里处理带有classpath标识的Resource
else if (location.startsWith(CLASSPATH_URL_PREFIX)) {
return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
}
else {
try {
// Try to parse the location as a URL...
// 这里处理URL标识的Resource定位
URL url = new URL(location);
return new UrlResource(url);
}
catch (MalformedURLException ex) {
// No URL -> resolve as resource path.
// 如果既不是classpath,也不是URL标识的Resource定位,则把getResource
// 的重任交给getResourceByPath,这个方法是一个protected方法,
// 默认的实现是得到一个ClassPathContextResource,这个方法常常会用子类来实现
return getResourceByPath(location);
}
}
}
我们需要注意的是其中getResourceByPath会被子类FileSystemXmlApplicationContext实现,而这个方法返回是一个FileSystemResource对象,通过这个对象,spring就可以进行相关的I/O操作,完成BeanDefinition的定位。其实它实现的是对path进行解析,然后生成一个FileSystemResource对象并返回。
到这里,我们就定位到了以FileSystem方式存在的Resource的定位实现。(水源找到了)
BeanDefinition的载入和解析
在完成对BeanDefinition的Resource定位分析后,我们来分析载入的过程,对Ioc容器来说,这个载入过程,相当于把定义的BeanDefinition在Ioc容器中转化为一个spring内部表示的数据结构。Ioc容器对Bean的管理和依赖注入功能的实现,是通过对其持有的BeanDefinition进行各种相关的操作来完成的。这些BeanDefinition数据在Ioc容器中通过一个HashMap来保持和维护。
对容器的启动来说,refresh是一个很重要的方法。该方法在AbstractApplicationContext类(它是FileSystemXmlApplicationContext的基类)中找到,它详细的描述了整个ApplicationContext的初始化过程,比如BeanFactory的更新,MessageSource和PostProcessor的注册等。
我们需要进入AbstractApplicationContext的子类AbstractRefreshableApplicationContext的refreshBeanFactory()方法中,在这个方法中创建了BeanFactory。在创建Ioc容器前,如果已经有容器存在,那么需要把已有的容器销毁和关闭,保证该refresh以后使用的是新建立起来的Ioc容器。而建立好当前deIoc容器后,开始了对容器的初始化过程,如BeanDefinition的载入。
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) { //判断,如果有,销毁已有的Ioc容器
destroyBeans();
closeBeanFactory();
}
try { //创建Ioc容器,这里使用的是DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory); //启动对BeanDefinition的载入
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
而这个方法是一个抽象方法,我们需要进入AbstractRefreshableApplicationContext的子类AbstractXmlApplicationContext中的实现这个抽象方法中去。在这个loadBeanDefinitions中,初始化了读取器XmlBeanDefinitionReader,然后把这个读取器在Ioc容器中设置好,最后是启动读取器来完成BeanDefinition在Ioc容器中的载入。
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);//这里设置XmlBeanDefinitionReader
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);//启动bean定义信息的载入过程
loadBeanDefinitions(beanDefinitionReader);
}
接着就是loadBeanDefinitions调用的地方,首先得到BeanDefinition信息的Resource定位,然后直接调用XmlBeanDefinitionReader来读取,具体的载入过程委托给BeanDefinitionReader完成的。
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
//以Resource的方式获得配置文件的资源位置
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
//以String的形式获得配置文件的位置
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
//以Resource的方式获得配置文件的资源位置
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
//以String的形式获得配置文件的位置
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
通过上面的分析,我们知道,在初始化FileSystemXmlApplicationContext的过程中是通过调用Ioc容器的refresh来启动整个BeanDefinition的载入过程的,这个初始化是通过定义的XmlBeanDefinitionReader来完成的。同时我们也知道,实际使用的Ioc容器是DefaultListableBeanFactory,具体的Resource载入在XmlBeanDefinitionReader读入BeanDefinition时实现。在XmlBeanDefinitionReader的实现中可以看到,是在reader.loadBeanDefinitions中开始进行BeanDefinition的载入的,而这时XmlBeanDefinitionReader的父类AbstractBeanDefinitionReader已经为BeanDefinition的载入做好了准备。
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
/*
* 如果启动的Resource为空,则停止BeanDefinition的载入
* 然后启动载入BeanDefinition的过程,这个过程会遍历整个Resource集合所包含的BeanDefinition信息
*/
Assert.notNull(resources, "Resource array must not be null");
int counter = 0;
for (Resource resource : resources) {
counter += loadBeanDefinitions(resource);
}
return counter;
}
在读取器中,需要得到代表XML文件的Resource,因为这个Resource对象封装了对XML文件的I/O操作,所以读取器可以在打开I/O流后得到XML文件对象。有了这个文件对象后,就可以按照spring的Bean定义规则来对这个XML的文档树进行解析了。
BeanDefinition的载入分成两部分,首先通过调用XML的解析器得到document对象,但这些document对象并没有按照spring的Bean规则进行解析。在完成通用的XML解析以后,才是按照spring的Bean规则进行解析的地方,这个按照spring的Bean规则进行解析的过程是在documentReader中实现的。其中对BeanDefinition的处理结果由BeanDefinitionHolder对象来持有,这个BeanDefinitionHolder除了持有BeanDefinition对象外,还持有其他与BeanDefinition相关的信息,比如Bean 的名字、别名集合等。这个BeanDefinitionHolder的生成是通过对Document文档树的内容进行解析来完成的。而这个解析过程是由BeanDefinitionParserDelegate来实现(具体在processBeanDefinition方法中实现)的。
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
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));
}
}
具体的spring BeanDefinition的解析是在BeanDefinitionParserDelegate中完成的,这个类包含了对各种spring Bean定义规则的处理,如常见的对BeanDefinition定义的处理,如id、name等属性元素。把这些元素的值从XML文件相应的元素的属性中读取出来以后,设置到生成的BeanDefinitionHolder中去。
我们以对一个property进行解析为例子。还是在类BeanDefinitionParserDelegate的代码中,一层一层地对BeanDefinition中的定义进行解释,比如从属性元素集合到具体的每一个属性元素,然后才是对具体的属性值的处理。根据解析结果,对这些属性值的处理会被封装成ProPerty Value对象并设置到BeanDefinition对象中去。
//这里对指定的Bean元素的property子元素集合进行解析
//遍历所有Bean元素下定义的property元素
public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
NodeList nl = beanEle.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {
//在判断是propert元素后对该property元素进行解析的过程
parsePropertyElement((Element) node, bd);
}
}
}
//这里取得property元素的值,也许是一个list或其他
public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) {
String elementName = (propertyName != null) ?
"<property> element for property '" + propertyName + "'" :
"<constructor-arg> element";
// Should only have one child element: ref, value, list, etc.
NodeList nl = ele.getChildNodes();
Element subElement = null;
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) &&
!nodeNameEquals(node, META_ELEMENT)) {
// Child element is what we're looking for.
if (subElement != null) {
error(elementName + " must not contain more than one sub-element", ele);
}
else {
subElement = (Element) node;
}
}
}
//这里判断property的属性,是ref还是value,不允许同时是ref和value
boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);
if ((hasRefAttribute && hasValueAttribute) ||
((hasRefAttribute || hasValueAttribute) && subElement != null)) {
error(elementName +
" is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
}
//如果是ref,创建一个ref的数据对象RuntimeBeanReference,这个对象封装了ref的信息
if (hasRefAttribute) {
String refName = ele.getAttribute(REF_ATTRIBUTE);
if (!StringUtils.hasText(refName)) {
error(elementName + " contains empty 'ref' attribute", ele);
}
RuntimeBeanReference ref = new RuntimeBeanReference(refName);
ref.setSource(extractSource(ele));
return ref;
}
//如果是value,创建一个value的数据对象TypeedStringValue,这个对象封装了value的信息
else if (hasValueAttribute) {
TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
valueHolder.setSource(extractSource(ele));
return valueHolder;
}
//如果还有子元素,触发对子元素的解析
else if (subElement != null) {
return parsePropertySubElement(subElement, bd);
}
else {
// Neither child element nor "ref" or "value" attribute found.
error(elementName + " must specify a ref or value", ele);
return null;
}
}
这里是对property子元素的解析过程,Array、List、Set、Map等各种元素都会在这里进行解析,生成对应的数据对象,比如ManagedList、ManagedArray、ManagedSet等。这些Managed类是Spring对具体的BeanDefinition的数据封装。
下面看一下List这样的属性配置是怎样被解析的,依然是在BeanDefinitionParserDelegate中,返回的是一个List对象,这个List是spring定义的ManagedList,作为封装List这类配置定义的数据封装。
public List<Object> parseListElement(Element collectionEle, BeanDefinition bd) {
String defaultElementType = collectionEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
NodeList nl = collectionEle.getChildNodes();
ManagedList<Object> target = new ManagedList<Object>(nl.getLength());
target.setSource(extractSource(collectionEle));
target.setElementTypeName(defaultElementType);
target.setMergeEnabled(parseMergeAttribute(collectionEle));
//具体的List元素的解析过程
parseCollectionElements(nl, target, bd, defaultElementType);
return target;
}
protected void parseCollectionElements(
NodeList elementNodes, Collection<Object> target, BeanDefinition bd, String defaultElementType) {
//遍历所有元素结点,并判断其类型是否为Element
for (int i = 0; i < elementNodes.getLength(); i++) {
Node node = elementNodes.item(i);
if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT)) {
//加入到target中,target是一个ManagedList,同时触发对一层子元素的解析过程
//这是一个递归调用
target.add(parsePropertySubElement((Element) node, bd, defaultElementType));
}
}
}
经过这样逐层的解析,我们在XML文件中定义的BeanDefinition就整个被载入到了Ioc容器中,并在容器中建立了数据映射,或者可以看成POJO对象在Ioc容器中的抽象,这些数据结构可以以AbstractBeanDefinition为入口,让Ioc容器执行索引、查询等操作。经过这些步骤,IOC容器大体上就完成了管理Bean对象的数据准备工作。但是重要的依赖注入这时实际上还没发生,现在,在Ioc容器BeanDefinition中存在的还只是一些静态配置信息。这时容器还没有完全起作用,要完全发挥容器的作用,还需完成数据向容器的注册。
BeanDefinitionz在Ioc容器中的注册
前面已经分析过BeanDefinition在Ioc容器中载入和解析的过程。在这些动作完成以后,用户定义的BeanDefinition信息已经在Ioc容器内建立起了自己的数据结构以及相应的数据表示,但此时这些数据还不能供Ioc容器的使用,需要在Ioc容器中对这些BeanDefinition数据进行注册。这个注册为Ioc容器提供了更友好的使用方式,在DefaultListableBeanFactory中,是通过一个HashMap来持有载入的BeanDefinition的,这个HashMap的定义在DefaultListableBeanFactory中可以看到:
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);
将解析得到的BeanDefinition向Ioc容器中的beanDefinitionMap注册的过程中是在载入BeanDefinition完成后进行的。
在DefaultListableBeanFactory中实现了BeanDefinitionRegistry接口,这个接口的实现完成BeanDefinition向容器的注册。这个注册过程并不复杂,就是把解析得到的BeanDefinition设置到hashmap中去。遇到同名的BeanDefinition,进行处理的时候需要依据allowBeanDefinitionOverriding的配置来完成。
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
//注册的过程需要synchronized,保证数据的一致性
synchronized (this.beanDefinitionMap) {
//这里检查是不是有相同名字的BeanDefinition已经在Ioc容器中注册了,
//如果有相同名字的BeanDefinition,但又不允许覆盖,那么会抛出异常。
BeanDefinition oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
if (!this.allowBeanDefinitionOverriding) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (this.logger.isWarnEnabled()) {
this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
" with a framework-generated bean definition ': replacing [" +
oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
else {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
}
/*
* 这是正常注册BeanDefinition的过程,把Bean的名字存入到BeanDefinitionName的同时,
* 把beanName作为Map的key,把beanDefinition作为value存入到Ioc容器持有的beanDefinition中去
*/
else {
this.beanDefinitionNames.add(beanName);
this.frozenBeanDefinitionNames = null;
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
resetBeanDefinition(beanName);
}
完成了BeanDefinition的注册,就完成了Ioc容器的初始化过程。此时,在使用的Ioc容器DefaultListableBeanFactory中已经建立了整个Bean的配置信息,而且这些BeanDefinition已经可以被容器使用了,他们都在beanDefinitionMap里被检索和使用。容器里的作用就是对这些信息进行处理和维护,这些信息是容器建立依赖反转的基础。
Ioc容器的依赖注入
Ioc容器的初始化过程主要是完成在Ioc容器中建立BeanDefinition数据映射。在此过程中并没有看到Ioc容器对Bean依赖关系进行注入。我们接下来就要分析Ioc容器是怎样对Bean的依赖关系进行注入的。
假设当前Ioc容器已经载入了用户定义的Bean信息,开始分析依赖注入的原理。首先,注意到依赖注入的过程是用户第一次向Ioc容器索要Bean时触发的,(也有例外,就是我们可以在BeanDefinition信息中通过lazy-init属性来让容器完成对Bean的预实例化,这个预实例化实际上也是一个完成依赖注入的过程,但他是在初始化的过程中完成的,后面会进行分析)。当用户向Ioc容器索要Bean时,在基本的Ioc容器接口BeanFactory中,有一个getBean的接口定义,这个接口的实现就是触发依赖注入发生的地方。我们需要从DefaultListableBeanFactory的基类AbstractBeanFactory入手去看看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 + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
/*
* 这里对Ioc容器中的BeanDefinition是否存在进行检查,
* 检查是否能在当前的BeanFactory中取得需要的Bean。如果
* 在当前的工厂中取不到,则到双亲BeanFactory中去取,
* 这个当前的双亲工厂取不到,那就顺着双亲BeanFactory链一直向上查找
*/
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
// 这里根据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) {
if (isDependent(beanName, dependsOnBean)) {
throw new BeanCreationException("Circular depends-on relationship between '" +
beanName + "' and '" + dependsOnBean + "'");
}
registerDependentBean(dependsOnBean, beanName);
getBean(dependsOnBean);
}
}
// 进入到createBean中进行详细分析
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 这里是创建prototype bean的地方
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
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<Object>() {
@Override
public Object getObject() throws BeansException {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; " +
"consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// 这里对创建的Bean进行类型检查,如果没有问题,就返回这个新创建的Bean,
// 这个Bean已经是包含了依赖关系的Bean
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type [" +
ClassUtils.getQualifiedName(requiredType) + "]", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
这个就是依赖注入的入口,在这里触发依赖注入,而依赖注入的发生是在容器中的BeanDefinition数据已经建立好的前提下进行的。“程序 = 数据 + 算法”,前面的BeanDefinition就是数据。
getBean是依赖注入的起点,之后会调用createBean,在这个过程中,Bean对象会依据BeanDefinition定义的要求生成。在AbstractAutowireCapableBeanFactory中实现了createBean,createBean不但生成了需要的Bean,还对Bean初始化进行了处理,比如实现了在BeanDefinition中的init-method属性定义。
protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
// 这里需要判断创建的Bean是否可以实例化,这个类是否可以通过类装载器来载入
resolveBeanClass(mbd, beanName);
// Prepare method overrides.
try {
mbd.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// 如果Bean配置了PostProceessor, 那么这里返回的是一个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;
}
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);
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
// 这里是对Bean的初始化,依赖注入往往在这里发生,这个exposedObject在初始化处理
// 完成以后会返回作为依赖注入完成后的Bean
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// 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来指定的。可以看到不同的生成方式对应的实现。
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
// 确认需要创建的Bean实例的类可以实例化
Class<?> beanClass = resolveBeanClass(mbd, beanName);
// 这里使用工厂方法对Bean进行实例化
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
return instantiateBean(beanName, mbd);
}
}
// 使用构造函数进行实例化
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// 使用默认的构造函数对Bean进行实例化
return instantiateBean(beanName, mbd);
}
// 最常见的实例化过程instantiateBean
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
// 使用默认的实例化策略对Bean进行实例化,默认的实例化策略是CglibSubclassingInstantiationStrategy
// 也就是使用CGLIB来对Bean进行实例化。
try {
Object beanInstance;
final BeanFactory parent = this;
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
return getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
}, getAccessControlContext());
}
else {
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}
在Ioc容器中,要了解怎样使用CGLIB来生成Bean对象,需要看一下SimpleInstantiationStratery。这个类是Spring用来生成Bean对象的默认类,它提供了两种实例化Java对象的方法,一种是通过BeanUtils,他使用了JVM的反射功能,一种是通过CGLIB生成。
public class SimpleInstantiationStrategy implements InstantiationStrategy {
public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
if (beanDefinition.getMethodOverrides().isEmpty()) {
// 这里取得指定的构造器或者生成对象的工厂方法来对Bean进行实例化。
Constructor<?> constructorToUse;
synchronized (beanDefinition.constructorArgumentLock) {
constructorToUse = (Constructor<?>) beanDefinition.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
final Class<?> clazz = beanDefinition.getBeanClass();
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {
@Override
public Constructor<?> run() throws Exception {
return clazz.getDeclaredConstructor((Class[]) null);
}
});
}
else {
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);
}
else {
// Must generate CGLIB subclass.
// 使用CGLIB来实例化对象
return instantiateWithMethodInjection(beanDefinition, beanName, owner);
}
}
}
到这里分析了实例化Bean对象的整个过程。在Bean对象生成以后,怎样把这些Bean的依赖关系设置好,完成整个依赖注入过程,这些依赖关系处理的依据就是已经解析得到的BeanDefinition。详细解释这个过程,我们需要populateBean方法,这个方法在AbstractAutowireCapableBeanFactory中的实现代码。
protected void populateBean(String beanName, RootBeanDefinition 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 {
// Skip property population phase for null instance.
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
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);
// Add property values based on autowire by name if applicable.
// 这里是对autowire注入的处理,可以根据Bean的名字或者类型
// 来完成Bean的autowire
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
// 对属性进行注入
applyPropertyValues(beanName, mbd, bw, pvs);
}
// 通过applyPropertyValues了解具体的对属性进行解析然后注入的过程
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
if (pvs == null || pvs.isEmpty()) {
return;
}
MutablePropertyValues mpvs = null;
List<PropertyValue> original;
if (System.getSecurityManager() != null) {
if (bw instanceof BeanWrapperImpl) {
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
}
}
if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues) pvs;
if (mpvs.isConverted()) {
// Shortcut: use the pre-converted values as-is.
try {
bw.setPropertyValues(mpvs);
return;
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
original = mpvs.getPropertyValueList();
}
else {
original = Arrays.asList(pvs.getPropertyValues());
}
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
// 注意这个BeanDefinitionValueResolve对BeanDefinition的解析
// 是在这个valueResolver中完成的
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
// Create a deep copy, resolving any references for values.
// 这里为解析值创建一个副本、副本的数据将会被载入到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);
}
// Possibly store converted value in merged bean definition,
// in order to avoid re-conversion for every created bean instance.
if (resolvedValue == originalValue) {
if (convertible) {
pv.setConvertedValue(convertedValue);
}
deepCopy.add(pv);
}
else if (convertible && originalValue instanceof TypedStringValue &&
!((TypedStringValue) originalValue).isDynamic() &&
!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
pv.setConvertedValue(convertedValue);
deepCopy.add(pv);
}
else {
resolveNecessary = true;
deepCopy.add(new PropertyValue(pv, convertedValue));
}
}
}
if (mpvs != null && !resolveNecessary) {
mpvs.setConverted();
}
// Set our (possibly massaged) deep copy.
// 这里是依赖注入发生的地方,会在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进行解析为例,
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
try {
// 从RuntimeBeanDefinitionReference取得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(new KeyedArgName(argName, i), 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(new KeyedArgName(argName, i), ml.get(i)));
}
return resolved;
}
这两种属性的注入都调用了resolveValueIfNecessary,这个方法包含了所有对注入类型的处理。
public Object resolveValueIfNecessary(Object argName, Object value) {
// We must check each value to see whether it requires a runtime reference
// to another bean to be resolved.
// 这里对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) {
// Resolve BeanDefinitionHolder: contains BeanDefinition with name and aliases.
BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;
return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
}
else if (value instanceof BeanDefinition) {
// Resolve plain BeanDefinition, without contained name: use dummy name.
BeanDefinition bd = (BeanDefinition) value;
String innerBeanName = "(inner bean)" + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR +
ObjectUtils.getIdentityHexString(bd);
return resolveInnerBean(argName, innerBeanName, bd);
}
// 这里对ManageArray进行解析
else if (value instanceof ManagedArray) {
// May need to resolve contained runtime references.
ManagedArray array = (ManagedArray) value;
Class<?> elementType = array.resolvedElementType;
if (elementType == null) {
String elementTypeName = array.getElementTypeName();
if (StringUtils.hasText(elementTypeName)) {
try {
elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());
array.resolvedElementType = elementType;
}
catch (Throwable ex) {
// Improve the message by showing the context.
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Error resolving array type for " + argName, ex);
}
}
else {
elementType = Object.class;
}
}
return resolveManagedArray(argName, (List<?>) value, elementType);
}
// 这里对ManageList进行解析
else if (value instanceof ManagedList) {
// May need to resolve contained runtime references.
return resolveManagedList(argName, (List<?>) value);
}
// 这里对ManageSet进行解析
else if (value instanceof ManagedSet) {
// May need to resolve contained runtime references.
return resolveManagedSet(argName, (Set<?>) value);
}
// 这里对ManageMap进行解析
else if (value instanceof ManagedMap) {
// May need to resolve contained runtime references.
return resolveManagedMap(argName, (Map<?, ?>) value);
}
// 这里对ManageProperties进行解析
else if (value instanceof ManagedProperties) {
Properties original = (Properties) value;
Properties copy = new Properties();
for (Map.Entry<Object, Object> propEntry : original.entrySet()) {
Object propKey = propEntry.getKey();
Object propValue = propEntry.getValue();
if (propKey instanceof TypedStringValue) {
propKey = evaluate((TypedStringValue) propKey);
}
if (propValue instanceof TypedStringValue) {
propValue = evaluate((TypedStringValue) propValue);
}
copy.put(propKey, propValue);
}
return copy;
}
// 这里对TypedStringVlues进行解析
else if (value instanceof TypedStringValue) {
// Convert value to target type here.
TypedStringValue typedStringValue = (TypedStringValue) value;
Object valueObject = evaluate(typedStringValue);
try {
Class<?> resolvedTargetType = resolveTargetType(typedStringValue);
if (resolvedTargetType != null) {
return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType);
}
else {
return valueObject;
}
}
catch (Throwable ex) {
// Improve the message by showing the context.
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(new KeyedArgName(argName, i), ml.get(i)));
}
return resolved;
}
在完成这个解析过程后,已经为依赖注入准备好了条件,这是真正把Bean对象设置到它所依赖的另一个Bean的属性中去的地方,其中处理的属性是各种各样的。依赖注入的发生是在BeanWrapper的setProperty Values中实现的,具体的完成却是在BeanWrapper的子类BeanWrapperImpl中实现的。
private void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {
String propertyName = tokens.canonicalName;
String actualName = tokens.actualName;
if (tokens.keys != null) {
// Apply indexes and map keys: fetch value for all keys but the last one.
// 设置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);
}
// Set value for last key.
String key = tokens.keys[tokens.keys.length - 1];
if (propValue == null) {
// null map value case
if (this.autoGrowNestedPaths) {
// TODO: cleanup, this is pretty hacky
int lastKeyIndex = tokens.canonicalName.lastIndexOf('[');
getterTokens.canonicalName = tokens.canonicalName.substring(0, lastKeyIndex);
propValue = setDefaultValue(getterTokens);
}
else {
throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + propertyName,
"Cannot access indexed value in property referenced " +
"in indexed property path '" + propertyName + "': returned null");
}
}
// 这里对Array进行注入
if (propValue.getClass().isArray()) {
PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);
Class<?> requiredType = propValue.getClass().getComponentType();
int arrayIndex = Integer.parseInt(key);
Object oldValue = null;
try {
if (isExtractOldValueForEditor() && arrayIndex < Array.getLength(propValue)) {
oldValue = Array.get(propValue, arrayIndex);
}
Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(),
requiredType, TypeDescriptor.nested(property(pd), tokens.keys.length));
Array.set(propValue, arrayIndex, convertedValue);
}
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<Object> list = (List<Object>) propValue;
int index = Integer.parseInt(key);
Object oldValue = null;
if (isExtractOldValueForEditor() && index < list.size()) {
oldValue = list.get(index);
}
Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(),
requiredType, TypeDescriptor.nested(property(pd), tokens.keys.length));
int size = list.size();
if (index >= size && index < this.autoGrowCollectionLimit) {
for (int i = size; i < index; i++) {
try {
list.add(null);
}
catch (NullPointerException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Cannot set element with index " + index + " in List of size " +
size + ", accessed using property path '" + propertyName +
"': List does not support filling up gaps with null elements");
}
}
list.add(convertedValue);
}
else {
try {
list.set(index, convertedValue);
}
catch (IndexOutOfBoundsException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Invalid list index in property path '" + propertyName + "'", ex);
}
}
}
// 这里对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<Object, Object> map = (Map<Object, Object>) propValue;
// IMPORTANT: Do not pass full property name in here - property editors
// must not kick in for map keys but rather only for map values.
TypeDescriptor typeDescriptor = (mapKeyType != null ?
TypeDescriptor.valueOf(mapKeyType) : TypeDescriptor.valueOf(Object.class));
Object convertedMapKey = convertIfNecessary(null, null, key, mapKeyType, typeDescriptor);
Object oldValue = null;
if (isExtractOldValueForEditor()) {
oldValue = map.get(convertedMapKey);
}
// Pass full property name and old value in here, since we want full
// conversion ability for map values.
Object convertedMapValue = convertIfNecessary(propertyName, oldValue, pv.getValue(),
mapValueType, TypeDescriptor.nested(property(pd), tokens.keys.length));
map.put(convertedMapKey, convertedMapValue);
}
else {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Property referenced in indexed property path '" + propertyName +
"' is neither an array nor a List nor a Map; returned value was [" + 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) {
if (pv.isOptional()) {
logger.debug("Ignoring optional value for property '" + actualName +
"' - property not found on bean class [" + getRootClass().getName() + "]");
return;
}
else {
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) {
final Method readMethod = pd.getReadMethod();
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers()) &&
!readMethod.isAccessible()) {
if (System.getSecurityManager()!= null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
readMethod.setAccessible(true);
return null;
}
});
}
else {
readMethod.setAccessible(true);
}
}
try {
if (System.getSecurityManager() != null) {
oldValue = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
return readMethod.invoke(object);
}
}, acc);
}
else {
oldValue = readMethod.invoke(object);
}
}
catch (Exception ex) {
if (ex instanceof PrivilegedActionException) {
ex = ((PrivilegedActionException) ex).getException();
}
if (logger.isDebugEnabled()) {
logger.debug("Could not read previous value of property '" +
this.nestedPath + propertyName + "'", ex);
}
}
}
valueToApply = convertForProperty(
propertyName, oldValue, originalValue, new TypeDescriptor(property(pd)));
}
pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);
}
// 这里取得注入属性的set方法,通过反射机制,把对象注入进去
final Method writeMethod = (pd instanceof GenericTypeAwarePropertyDescriptor ?
((GenericTypeAwarePropertyDescriptor) pd).getWriteMethodForActualAccess() :
pd.getWriteMethod());
if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers()) && !writeMethod.isAccessible()) {
if (System.getSecurityManager()!= null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
writeMethod.setAccessible(true);
return null;
}
});
}
else {
writeMethod.setAccessible(true);
}
}
final Object value = valueToApply;
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
writeMethod.invoke(object, value);
return null;
}
}, acc);
}
catch (PrivilegedActionException ex) {
throw ex.getException();
}
}
else {
writeMethod.invoke(this.object, value);
}
}
catch (TypeMismatchException ex) {
throw ex;
}
catch (InvocationTargetException ex) {
PropertyChangeEvent propertyChangeEvent =
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
if (ex.getTargetException() instanceof ClassCastException) {
throw new TypeMismatchException(propertyChangeEvent, pd.getPropertyType(), ex.getTargetException());
}
else {
throw new MethodInvocationException(propertyChangeEvent, ex.getTargetException());
}
}
catch (Exception ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
throw new MethodInvocationException(pce, ex);
}
}
}
这样就完成了对各种Bean属性的依赖注入过程。在Bean的创建和对象依赖注入的过程中,需要依据BeanDefinition中的信息来递归地完成依赖注入。从上面的几个递归过程中可以看到,这些递归都是以getBean为入口的。一个递归是在上下文体系中查找需要的Bean和创建Bean 的递归调用;另一个递归是在依赖注入时,通过递归调用容器的getBean方法,得到当前Bean的依赖Bean,同时也触发对依赖Bean的创建和注入,一层一层地完成Bean的创建和注入,直到最后完成当前Bean的创建。有了这个顶层Bean的创建和对它的属性依赖注入的完成,意味着和当前Bean相关的整个依赖链的注入也完成了。
在Bean 创建和依赖注入完成以后,在Ioc容器中建立起一系列依靠依赖关系联系起来的Bean,这个Bean已经不是简单的Java对象了。该Bean系列以及Bean之间的依赖关系建立完成以后,通过Ioc容器的相关接口方法,就可以非常方便地供上层应用使用了。