一、IOC原理
Spring功能如此强大,但是再强大的功能也是用java代码写出来的,那么就来看看IOC的实现原理是什么。
上一章说到,由于bean中lazy-init属性的存在,我们没有办法一次性将所有bean全部实例化,并且放到一个Map
package org.springframework.beans.factory.support;
import java.io.NotSerializableException;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import javax.inject.Provider;
import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanCurrentlyInCreationException;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.CannotLoadBeanClassException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.SmartFactoryBean;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/** * @author Rod Johnson * @author Juergen Hoeller * @author Sam Brannen * @author Costin Leau * @since 16 April 2001 */
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
private static Class javaxInjectProviderClass = null;
static {
ClassLoader cl = DefaultListableBeanFactory.class.getClassLoader();
try {
javaxInjectProviderClass = cl.loadClass("javax.inject.Provider");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - Provider interface simply not supported then.
}
}
/** Map from serialized id to factory instance */
private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories =
new ConcurrentHashMap<String, Reference<DefaultListableBeanFactory>>();
/** Optional id for this factory, for serialization purposes */
private String serializationId;
/** Whether to allow re-registration of a different definition with the same name */
private boolean allowBeanDefinitionOverriding = true;
/** Whether to allow eager class loading even for lazy-init beans */
private boolean allowEagerClassLoading = true;
/** Resolver to use for checking if a bean definition is an autowire candidate */
private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver();
/** Map from dependency type to corresponding autowired value */
private final Map<Class, Object> resolvableDependencies = new HashMap<Class, Object>();
/** Map of bean definition objects, keyed by bean name */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();
/** List of bean definition names, in registration order */
private final List<String> beanDefinitionNames = new ArrayList<String>();
/** Whether bean definition metadata may be cached for all beans */
private boolean configurationFrozen = false;
/** Cached array of bean definition names in case of frozen configuration */
private String[] frozenBeanDefinitionNames;
}
果不其然,是它是它就是它。
/** Map of bean definition objects, keyed by bean name */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();
和我们设想的是一样的,这个实现类里面定义了这样一个Map,看注释,bean的name值作为这个Map的key值,所以,我们需要哪个bean,就从这个map里面找就行了。
这里,IOC容器的原理就清晰很多了,只要把配置文件里面的bean标签按照规则读取出来,然后以name为key,BeanDefinition对象为value值存放在这个map中,当我们getBean时,实际上就是从这个map中取一个对象的过程,那么IOC容器的原理可以总结为:
1、需要一个File对象指向我们的xml配置文件,也就是说,我们需要找到xml文件的具体位置,也叫资源定位。
2、需要一个Reader读取我们的xml文件,把bean标签一个个读取出来,也叫DOM解析
3、将读取出来的bean标签放到一个Map当中
说实话,看到这里,Spring在我心中那神秘又伟岸的形象瞬间崩塌了,这特么也不见得很高级啊。回过头想想,再牛逼的技术也是有简简单单的东西组合实现的。继续说。
既然已经知道了IOC的原理,我们就可以自己来做一个获取bean的过程了。
首先来个测试类:
public class User {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
配置文件:
<bean id="user" class="com.errol.dao.User">
<property name="name">
<value>宝宝</value>
</property>
</bean>
测试类:
public class Client {
@Test
public void testFactory(){
/* * 下面使用的都是Spring的类或者接口 */
//资源定位
ClassPathResource cr = new ClassPathResource("applicationContext.xml");
//bean工厂
DefaultListableBeanFactory db = new DefaultListableBeanFactory();
//解析xml的工具
XmlBeanDefinitionReader xd = new XmlBeanDefinitionReader(db);
//解析xml并且存放到map
xd.loadBeanDefinitions(cr);
System.out.println("bean的个数:"+db.getBeanDefinitionCount());
User user = (User)db.getBean("user");
System.out.println(user);
}
}
输出结果:
log4j:WARN No appenders could be found for logger (org.springframework.core.CollectionFactory).
log4j:WARN Please initialize the log4j system properly.
bean的个数:1
com.errol.dao.User@900bac2
成功!
接下来,联想一下平时我们用的ApplicationContext对象去获取bean时候的用法
ApplicationContext applicationContext = new ClassPathXMLApplicationContext("applicationContext");
User user = new applicationContext .getBean("user");
我们四步做完的事情,上面一步就解决了,new ClassPathXMLApplicationContext(“applicationContext”);这句话里面到底做了什么呢?
二、IOC容器初始化过程
我们来看看ClassPathXMLApplicationContext这个方法里面到底有什么猫腻,把我们四步实现变成了一步。进入这个方法看一看:
public ClassPathXmlApplicationContext(String[] configLocations, ApplicationContext parent)
throws BeansException {
super(parent);
this.configLocations = configLocations;
refresh();
}
里面就调用了一个refresh方法,在进去看看,进入到AbstracApplicationContext的一个抽象类中,ClassPathXmlApplicationContext就是继承自这个抽象类,只不过中间还有两层,AbstractXmlApplicationContext和AbstractRefreshableApplicationContext两个抽象类。
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
this.startupTime = System.currentTimeMillis();
synchronized (this.activeMonitor) {
this.active = true;
}
// Tell subclass to refresh the internal bean factory.
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// Tell the internal bean factory to use the context's class loader.
beanFactory.setBeanClassLoader(getClassLoader());
// Populate the bean factory with context-specific resource editors.
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this));
// Configure the bean factory with context semantics.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered with the context instance.
for (Iterator it = getBeanFactoryPostProcessors().iterator(); it.hasNext();) {
BeanFactoryPostProcessor factoryProcessor = (BeanFactoryPostProcessor) it.next();
factoryProcessor.postProcessBeanFactory(beanFactory);
}
if (logger.isInfoEnabled()) {
if (getBeanDefinitionCount() == 0) {
logger.info("No beans defined in application context [" + getDisplayName() + "]");
}
else {
logger.info(getBeanDefinitionCount() + " beans defined in application context [" + getDisplayName() + "]");
}
}
try {
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors();
// Register bean processors that intercept bean creation.
registerBeanPostProcessors();
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate singletons this late to allow them to access the message source.
beanFactory.preInstantiateSingletons();
// Last step: publish corresponding event.
publishEvent(new ContextRefreshedEvent(this));
}
catch (BeansException ex) {
// Destroy already created singletons to avoid dangling resources.
beanFactory.destroySingletons();
throw ex;
}
}
}
这里面主要看refreshBeanFactory方法,但是这个抽象类中没有实现,来找找它的子类,上面说的几个,一个个看过去,在
AbstractRefreshableApplicationContext抽象类中,有这个方法的实现,来看一下:
protected final void refreshBeanFactory() throws BeansException {
// Shut down previous bean factory, if any.
synchronized (this.beanFactoryMonitor) {
if (this.beanFactory != null) {
this.beanFactory.destroySingletons();
this.beanFactory = null;
}
}
// Initialize fresh bean factory.
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
if (logger.isInfoEnabled()) {
logger.info("Bean factory for application context [" + getDisplayName() + "]: " + beanFactory);
}
}
catch (IOException ex) {
throw new ApplicationContextException(
"I/O error parsing XML document for application context [" + getDisplayName() + "]", ex);
}
}
上面的实现,我们熟悉的东西出现了:DefaultListableBeanFactory beanFactory,这不就是上面我们用四步的中的一步吗,创建这个DefaultListableBeanFactory 的实例对象,然后后面就是解析DOM,将bean标签解析成BeanDefinition对象,放到Map中,来看看,这里是不是这么实现的,进去loadBeanDefinitions方法,发现这里也没实现,往子类找,AbstractXmlApplicationContext中对这个方法有了实现,进去看一下:
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws 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.setResourceLoader(this);
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);
loadBeanDefinitions(beanDefinitionReader);
}
熟悉的东西XmlBeanDefinitionReader,读取资源文件中的bean定义,initBeanDefinitionReader方法在这个类中没有实现,按照字面意思就是初始化我们的beanDefinitionReader,关键是后面那个方法loadBeanDefinitions(beanDefinitionReader);这不就是我们写的四步中的一步么,只是它经过了层层封装,用一步就能搞定我们要做的事情,那么来看看XmlBeanDefinitionReader中这个方法loadBeanDefinitions是如何实现的就完成摸透了IOC的初始化过程 。。。。。的一半了。
三、loadBeanDefinitions方法详解
顺着我们的源码一直往下找,在org.springframework.beans.factory.xml.XmlBeanDefinitionReader这个类中,找到了loadBeanDefinitions方法的实现:
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isInfoEnabled()) {
logger.info("Loading XML bean definitions from " + encodedResource.getResource());
}
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<EncodedResource>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected recursive loading of " + encodedResource + " - check your import definitions!");
}
//这里得到XML文件,并得到IO的InputSource准备进行读取。
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) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.set(null);
}
}
}
里面主要关注一下doLoadBeanDefinitions方法,这个方法是具体的读取bean的详细过程:
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
int validationMode = getValidationModeForResource(resource);
//这里取得XML文件的Document对象,这个解析过程是由 documentLoader完成的,这个documentLoader是DefaultDocumentLoader,在定义documentLoader的地方创建
Document doc = this.documentLoader.loadDocument(
inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());
//这里启动的是对BeanDefinition解析的详细过程,这个解析会使用到Spring的Bean配置规则,是我们下面需要详细关注的地方。
return registerBeanDefinitions(doc, resource);
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (SAXParseException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
}
catch (SAXException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"XML document from " + resource + " is invalid", ex);
}
catch (ParserConfigurationException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Parser configuration exception parsing XML from " + resource, ex);
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"IOException parsing XML document from " + resource, ex);
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Unexpected exception parsing XML document from " + resource, ex);
}
}
定位到了另一个方法:registerBeanDefinitions,这个方法里面就是详细的解析过程了。顺着这个方法下去,找到了接口BeanDefinitionDocumentReader,接口中没有实现,看看子类DefaultBeanDefinitionDocumentReader,有这个方法的实现
/** * Parses bean definitions according to the "spring-beans" DTD. * <p>Opens a DOM Document; then initializes the default settings * specified at <code><beans></code> level; then parses * the contained bean definitions. */
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
BeanDefinitionParserDelegate delegate = createHelper(readerContext, root);
preProcessXml(root);
parseBeanDefinitions(root, delegate);
postProcessXml(root);
}
再次定位到一个方法parseBeanDefinitions,再进去:
/** * Parse the elements at the root level in the document: * "import", "alias", "bean". * @param root the DOM root element of the document */
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
// 解析import, alias, beans等默认标签
parseDefaultElement(ele, delegate);
}
else {
// 解析aop, mvc, dubbo等自定义标签,这部分在文末解释
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
这里需要说明的一点是:关于具体的Spring BeanDefinition的解析,是在BeanDefinitionParserDelegate中完成的。这个类里包含了各种Spring Bean定义规则的处理,感兴趣的同学可以仔细研究。我们举一个例子来分析这个处理过程,比如我们最熟悉的对Bean元素的处理是怎样完成的,也就是我们在XML定义文件中出现的这个最常见的元素信息是怎样被处理的。在这里,我们会看到那些熟悉的BeanDefinition定义的处理,比如id、name、aliase等属性元素。把这些元素的值从XML文件相应的元素的属性中读取出来以后,会被设置到生成的BeanDefinitionHolder中去。这些属性的解析还是比较简单的。对于其他元素配置的解析,比如各种Bean的属性配置,通过一个较为复杂的解析过程,这个过程是由parseBeanDefinitionElement来完成的。解析完成以后,会把解析结果放到BeanDefinition对象中并设置到BeanDefinitionHolder中去。
在BeanDefinitionParserDelegate类中的这个方法,这里只贴了部分代码,太多了,是对bean标签详细解析过程,看返回值,是一个AbstractBeanDefinition 的实例,也就是说,解析出来就是BeanDefinition对象。
/** * Parse the bean definition itself, without regard to name or aliases. May return * <code>null</code> if problems occured during the parse of the bean definition. */
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, BeanDefinition containingBean) {
String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE);
}
String parent = null;
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
说到这里,我们再来理一下:
1、BeanDefinitionParserDelegate解析bean标签,生成一个AbstractBeanDefinition 对象
2、生成的AbstractBeanDefinition 对象放到了BeanDefinitionHolder对象中
3、BeanFactory对象调用registerBeanDefinition方法,将BeanDefinitionHolder中的AbstractBeanDefinition 对象注册到****Map当中去。这就与上面的逻辑连接通了。
我们举一个对property进行解析的例子来完成对整个BeanDefinition载入过程的分析,还是在类BeanDefinitionParserDelegate的代码中,它对BeanDefinition中的定义一层一层地进行解析,比如从属性元素集合到具体的每一个属性元素,然后才是对具体的属性值的处理。根据解析结果,对这些属性值的处理会封装成PropertyValue对象并设置到BeanDefinition对象中去,如以下代码清单所示。
/** * 这里对指定bean元素的property子元素集合进行解析。 */
public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
//遍历所有bean元素下定义的property元素
NodeList nl = beanEle.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element && DomUtils.nodeNameEquals(node, PROPERTY_ELEMENT)) {
//在判断是property元素后对该property元素进行解析的过程
parsePropertyElement((Element) node, bd);
}
}
}
public void parsePropertyElement(Element ele, BeanDefinition bd) {
//这里取得property的名字
String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
if (!StringUtils.hasLength(propertyName)) {
error("Tag 'property' must have a 'name' attribute", ele);
return;
}
this.parseState.push(new PropertyEntry(propertyName));
try {
//如果同一个bean中已经有同名的存在,则不进行解析,直接返回。也就是说,如果在同一个bean中有同名的property设置,那么起作用的只是第一个。
if (bd.getPropertyValues().contains(propertyName)) {
error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
return;
}
//这里是解析property值的地方,返回的对象对应对Bean定义的property属性设置的解析结果,这个解析结果会封装到PropertyValue对象中,然后设置到BeanDefinitionHolder中去。
Object val = parsePropertyValue(ele, bd, propertyName);
PropertyValue pv = new PropertyValue(propertyName, val);
parseMetaElements(ele, pv);
pv.setSource(extractSource(ele));
bd.getPropertyValues().addPropertyValue(pv);
}
finally {
this.parseState.pop();
}
}
/** * 这里取得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 && !DomUtils.nodeNameEquals(node, DESCRIPTION_ELEMENT) &&
!DomUtils.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的数据对象TypedStringValue ,这个对象封装了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;
}
}
上面提到了对ref属性的解析,同时提到了一个类RuntimeBeanReference,这个类实现自BeanReference,这个接口很简单,就一个方法String getBeanName();这个接口存储的就是bean与bean之间的依赖关系,就比如ref标签,在property对象中,就是ref指向一个BeanReference引用,这个引用中对应的就是依赖的那个bean的信息,通过getBeanName就能获取到那个bean的名称,也就能获取到BeanDefinition对象了。
经过这样一层一层的解析,我们在XML文件中定义的BeanDefinition就被整个给载入到了IoC容器中,并在容器中建立了数据映射。在IoC容器中建立了对应的数据结构,或者说可以看成是POJO对象在IoC容器中的映像,这些数据结构可以以AbstractBeanDefinition为入口,让IoC容器执行索引、查询和操作。
上面我们贴了一小段.BeanDefinitionParserDelegate类代码的开头,定义的是bean的一些属性,其实下面都有对应属性的解析方法,上面贴的只是对Property属性的解析过程。
在DefaultBeanDefinitionDocumentReader的parseBeanDefinitions中,上面提到的对一些默认的属性,调用的是BeanDefinitionParserDelegate的parseCustomElement,如果不是默认的标签,比如自定义的,注解,还有AOP的,将调用另一个方法parseCustomElement,这个逻辑也是相对复杂,涉及到后面的内容,这里暂时不作解析,后面再补上来。
总结一下IOC的原理:
1、IOC的核心就是容器的初始化,首先我们定义一个容器,都是BeanFactory接口的实现类
2、容器进行初始化,调用的的refreshBeanFactory()方法进行初始化。
3、初始化的过程主要包括,读取xml配置文件
4、将每一个bean标签通过BeanDefinitionParserDelegate的parseDefaultElement或者parseCustomElement方法读取出来,并且存放到AbstractBeanDefinition对象中
5、将AbstractBeanDefinition对象再保存到BeanDefinitionHolder对象中
6、BeanFactory中有一个Map