2,spring中IOC的实现【analyze spring framework source】

接上一篇 1. Introduce how to import the Spring Framework sourcecode into an eclipse project html

一. 结构 java

spring中bean管理设计到下面3个包 node

 

image

core 至关于一个工具类,bean包是对IOC的实现包,context是在bean的基础扩展功能 spring

 

IOC的实现原理简介 app

简单实现 dom

package org.benson; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.core.io.ClassPathResource; public class Test4DebugSpringIOC { ConfigurableListableBeanFactory beanFactory = new DefaultListableBeanFactory();//manage bean factory ClassPathResource resource = new ClassPathResource( "applicationContext.xml");//resource XmlBeanDefinitionReader xmlReader=new XmlBeanDefinitionReader((BeanDefinitionRegistry)beanFactory); //register public Test4DebugSpringIOC() { // TODO load and registered BeanDefinition  xmlReader.loadBeanDefinitions(resource); } public static void main(String[] args) { Test4DebugSpringIOC test4DebugSpring= new Test4DebugSpringIOC(); Test4DebugSpringBean test4DebugSpringBean = (Test4DebugSpringBean) test4DebugSpring.beanFactory .getBean("testAlias"); test4DebugSpringBean.SayHolle(); } }

 

 1,找到bean的定义文件(Resource) eclipse

      如此处classPathResource,用于找到文件位置 ide

 2,把定义文件解析成BeanDefinition对象,用BeanDefinitionReader 工具

  i 调用DefaultDocumentLoader把XML解析成DOC并进行XSD,DTD等格式验证.
post

 DefaultDocumentLoader调用了SAX的DocumentBuilderFactory.newInstance(),把XML文件解析成一个org.w3c.dom.Document对象

(顺带提句,不能用JDOM,缘由就是内存,此处this.errorHandler也是SAX的一个事件接口,SAX XML解析是事件解析)
int validationMode = getValidationModeForResource(resource);//Validation xml file . XmlBeanDefinitionReader doLoadBeanDefinitions Document doc = this.documentLoader.loadDocument( inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());//parse to doc . through documentLoader(DefaultDocumentLoader) return registerBeanDefinitions(doc, resource);

ii DefaultBeanDefinitionDocumentReader读取document中的全部Element. 

registerBeanDefinitions(doc, resource)中调用BeanDefinitionDocumentReader的registerBeanDefinitions方法获根节点

public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		this.readerContext = readerContext;

		logger.debug("Loading bean definitions");
		Element root = doc.getDocumentElement();

		doRegisterBeanDefinitions(root);
	}

获得XML的根节点,调用doRegisterBeanDefinitions

/** * Register each bean definition within the given root {@code <beans/>} element. * @throws IllegalStateException if {@code <beans profile="..."} attribute is present * and Environment property has not been set * @see #setEnvironment */ protected void doRegisterBeanDefinitions(Element root) { ..//profile // any nested <beans> elements will cause recursion in this method. In // order to propagate and preserve <beans> default-* attributes correctly, // keep track of the current (parent) delegate, which may be null. Create // the new (child) delegate with a reference to the parent for fallback purposes, // then ultimately reset this.delegate back to its original (parent) reference. // this behavior emulates a stack of delegates without actually necessitating one. BeanDefinitionParserDelegate parent = this.delegate; this.delegate = createHelper(readerContext, root, parent); preProcessXml(root); parseBeanDefinitions(root, this.delegate); postProcessXml(root); this.delegate = parent; }

 

而后从得到根结点的全部子节点,进行循环

/** * 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)) { parseDefaultElement(ele, delegate);//parse defalut element  } else { delegate.parseCustomElement(ele); } } } } else { delegate.parseCustomElement(root); } }

 parseDefaultElement(ele, delegate),若是发现是bean标签则调用processBeanDefinition方法

/** * Process the given bean element, parsing the bean definition * and registering it with the registry. */ protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); //parse to object of BeanDefinitionHolder if (bdHolder != null) {//if it is not exit. parse it from xml 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)); } }

iii 调用BeanDefinitionParserDelegate对象完成doc中Element->BeanDefinitionHolder的转换

/** * Parses the supplied <code>&lt;bean&gt;</code> element. May return <code>null</code> * if there were errors during parse. Errors are reported to the * {@link org.springframework.beans.factory.parsing.ProblemReporter}. */ public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) { String id = ele.getAttribute(ID_ATTRIBUTE); String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); ... ... //vacation AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); .... return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); }

 

 

 

先得到别名,这里叫nameAttr,而后各类相关解析

/** * Parse the bean definition itself, without regard to name or aliases. May return * <code>null</code> if problems occurred during the parsing of the bean definition. */ public AbstractBeanDefinition parseBeanDefinitionElement( Element ele, String beanName, BeanDefinition containingBean) { this.parseState.push(new BeanEntry(beanName)); String className = null; if (ele.hasAttribute(CLASS_ATTRIBUTE)) { className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); } try { String parent = null; if (ele.hasAttribute(PARENT_ATTRIBUTE)) { parent = ele.getAttribute(PARENT_ATTRIBUTE); } AbstractBeanDefinition bd = createBeanDefinition(className, parent); parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT)); parseMetaElements(ele, bd); parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); parseConstructorArgElements(ele, bd); parsePropertyElements(ele, bd); parseQualifierElements(ele, bd); bd.setResource(this.readerContext.getResource()); bd.setSource(extractSource(ele)); return bd; }

 

反正所有当成属性设置到了AbstractBeanDefinition中,具体能够看AbstractBeanDefinition类

最后返回BeanDefinitionHolder;BeanDefinitionHolder是由beanname+aliasArray+beandefinition组成的一个对象

 

IV 而后回到ii的最后调用BeanDefinitionReaderUtils.registerBeanDefinition注册beandefine对象,并调BeanDefinitionRegistry接口进行注册,如DefaultListableBeanFactory

完成转换后,BeanDefinitionReaderUtils.registerBeanDefinition 调用到 BeanDefinitionRegistry接口实现类的registerBeanDefinition方法把对象放入bean的工厂容器中

* Register the given bean definition with the given bean factory. * @param definitionHolder the bean definition including name and aliases * @param registry the bean factory to register with * @throws BeanDefinitionStoreException if registration failed */ public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException { // Register bean definition under primary name. String beanName = definitionHolder.getBeanName(); registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); // Register aliases for bean name, if any. String[] aliases = definitionHolder.getAliases(); if (aliases != null) { for (String aliase : aliases) { registry.registerAlias(beanName, aliase); } } }

 在DefaultListableBeanFactory的实现也很简单了,直接用map添加下就OK了

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { ....//Validation this.beanDefinitionMap.put(beanName, beanDefinition);//add it to beanDefinitionMap  } resetBeanDefinition(beanName); //reset all exist }

 

 3,查找,经过getbean得到bean,用ConfigurableListableBeanFactory,如DefaultListableBeanFactory

这部分功能主要在abstractbeanfactory中完成,若是是singleton(即spring的default)

i   transformedBeanName(name) ,获得SimpleAliasRegistry 的 map 属性 aliasMap,转换为beanname(别名功能)

ii  Object sharedInstance = getSingleton(beanName); 尝试从DefaultSingletonBeanRegistry的MAP singletonObjects中拿出bean (singleton功能)

iii  bean = getObjectForBeanInstance(sharedInstance, name, beanName, null) 处理factorybean部分,附 Spring FactoryBean源码浅析

iv final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 从bean注册的信息中找到bean 对应的 BeanDefinition

v return createBean(beanName, mbd, args); 建立新的bean,经过BeanDefinition的描述信息来,并填充到DefaultSingletonBeanRegistry的singletonObjects中

beanfactory的主要代码,加上了些注释

 

/** * Return an instance, which may be shared or independent, of the specified bean. * @param name the name of the bean to retrieve * @param requiredType the required type of the bean to retrieve * @param args arguments to use if creating a prototype using explicit arguments to a * static factory method. It is invalid to use a non-null args value in any other case. * @param typeCheckOnly whether the instance is obtained for a type check, * not for actual use * @return an instance of the bean * @throws BeansException if the bean could not be created */ @SuppressWarnings("unchecked") protected <T> T doGetBean( final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException { final String beanName = transformedBeanName(name); //get true name from attribute aliasMap of SimpleAliasRegistry  Object bean; // Eagerly check singleton cache for manually registered singletons. Object sharedInstance = getSingleton(beanName); //get instance object from the attribute singletonObjects of DefaultSingletonBeanRegistry 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); // it is for that class witch is implement interface factorybean  } else { // Fail if we're already creating this bean instance: // We're assumably within a circular reference. if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // Check if bean definition exists in this factory. 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); } final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);//get BeanDefinition from registered information  checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on. String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dependsOnBean : dependsOn) { getBean(dependsOnBean); registerDependentBean(dependsOnBean, beanName); } } // Create bean instance. if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { //create new instance and put in attribute map singletonObjects of DefaultSingletonBeanRegistry 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); } 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>() { 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); } } } // Check if required type matches the type of the actual bean instance. 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; }

 

 

 

 

附 bean中的主要结构

主要类,下列类从上往下继承

SimpleAliasRegistry 用于维护一个 aliasMap,维护别名功能

DefaultSingletonBeanRegistry map 维护 singletonObjects,维护工厂单例,一个工厂一个单例,非N个工厂一个单例

FactoryBeanRegistrySupport

AbstractBeanFactory ,factorybean的主要实现类,其doGetBean,getBean是主要得到bean的入口 ,维护一个mergedBeanDefinitions

AbstractAutowireCapableBeanFactory,configureableBeanFactory的主要实现类,  createBean根据beandefine的信息建立相应的值

DefaultListableBeanFactory ConfigurableListableBeanFactory和BeanDefinitionRegistry接口的主要实现类,维护beanDefiniti信息

 

 

 

image

 

bean中ConfigurableListableBeanFactory接口继承了bean中的基本接口,DefaultListableBeanFactory是其惟一实现类

接口由于能够多继承,因此用来表示系统的结构最合适不过,而JAVA中类单继承的,通常只是用来实现设计,侧重实现功能,由于类层次确定是一条线。

 

2B青年欢乐多啊,没事研究下spring源码,继续补充更新中,有兴趣加企鹅一块儿研究108966750

相关文章
相关标签/搜索